home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection 1998 Fall: Game Toolkit / Disc.iso / SDKs / Apple Game Sprockets / InputSprocket / Sample Drivers / ISp Sample USB Sources / ISpSampleUSB.cp next >
Encoding:
Text File  |  1998-07-23  |  88.8 KB  |  3,086 lines  |  [TEXT/CWIE]

  1. /*************************************************************************************
  2.  
  3. File:      ISpSampleUSB.cp
  4.  
  5. Copyright © 1996, 1997, 1998 Apple Computer, Inc., All Rights Reserved
  6.  
  7.  
  8. You may incorporate this sample code into your applications without
  9. restriction, though the sample code has been provided "AS IS" and the
  10. responsibility for its operation is 100% yours.  However, what you are
  11. not permitted to do is to redistribute the source as "DSC Sample Code"
  12. after having made changes. If you're going to re-distribute the source,
  13. we require that you make it clear in the source that the code was
  14. descended from Apple Sample Code, but that you've made changes.
  15.  
  16. *************************************************************************************/
  17.  
  18. #ifndef __INPUTSPROCKET__
  19. #include <InputSprocket.h>
  20. #endif
  21.  
  22. #include "InputSprocketDriver.h"
  23. #include "ISpSampleUSB.h"
  24.  
  25. #ifndef __RESOURCES__
  26. #include <Resources.h>
  27. #endif
  28.  
  29. #ifndef __TEXTUTILS__
  30. #include <TextUtils.h>
  31. #endif
  32.  
  33. #ifndef __QDOFFSCREEN__
  34. #include <QDOffscreen.h>
  35. #endif
  36.  
  37. #ifndef __DESKBUS__
  38. #include <DeskBus.h>
  39. #endif
  40.  
  41. #include <USB.h>
  42.  
  43. #include "UniversalHIDModule.h"
  44.  
  45. #include "ISpPlugInUI.h"
  46. #include "dprintf.h"
  47.  
  48. #include "Common.h"
  49. #include "DialogUtils.h"
  50. #include "ListUtils.h"
  51. #include "ResourceUtils.h"
  52. #include "String_Utils.h"
  53.  
  54. List *                ISpUSBDevice::gUSBDevices;
  55.  
  56. static ISpElementLabel USBElementKeyToLabel(short usbElementKey);
  57.  
  58. extern "C" void MyUHIDInterruptProc (void *theData, UInt32 refcon);
  59.  
  60. ISpUSBDevice::ISpUSBDevice(
  61.     const UHIDModuleDispatchTablePtr hidmoduleDispatchTable,
  62.     const USBDeviceRef usbDeviceRef,
  63.     const FSSpec &inFileSpec)
  64. {
  65.     // assign our arguments
  66.     mHIDModuleDispatchTable = 0;
  67.  
  68.     // Save our ref    (must happen before callback install)
  69.     mUSBDeviceRef = usbDeviceRef;
  70.  
  71.     {
  72.         mConnectionNotifyPB.usbDeviceNotification = kNotifyRemoveInterface;
  73.         mConnectionNotifyPB.usbClass = kUSBHIDClass;
  74.         mConnectionNotifyPB.usbSubClass = kUSBNoInterfaceSubClass;
  75.         mConnectionNotifyPB.usbProtocol = kUSBNoInterfaceProtocol;
  76.         mConnectionNotifyPB.usbVendor = -1;
  77.         mConnectionNotifyPB.usbProduct = -1;
  78.         mConnectionNotifyPB.callback = (USBDeviceNotificationCallbackProcPtr) &ISpUSBDevice::UIDNotifyProc;
  79.         mConnectionNotifyPB.refcon = (UInt32) this;
  80.  
  81.         ::USBInstallDeviceNotification(&mConnectionNotifyPB);
  82.         if (noErr == mConnectionNotifyPB.result)
  83.         {
  84.             mHIDModuleDispatchTable = hidmoduleDispatchTable;
  85.         }
  86.     }
  87.  
  88.     mFileSpec = inFileSpec;
  89.     
  90.     // clear the device
  91.     mDevice = nil;
  92.  
  93.     // intialize ui variables
  94.     mDialog                 = nil;
  95.     mBaseDITLCount            = nil;
  96.     mResRef                 = nil;
  97.     mVisable                 = false;
  98.     mVirtualElementsValid     = false;    // Init has not been called yet
  99.     mActive                 = false;
  100.     mPatched                = false;
  101.  
  102.     mReverseStick = false;
  103.     mReverseRudder = false;
  104.     mReverseThrottle = false;
  105.     mReverseThrottle = false;
  106.     mReverseRudder = false;
  107.     mReverseDPad[0] = false;
  108.     mReverseDPad[1] = false;
  109.     mReverseDPad[2] = false;
  110.     mReverseDPad[3] = false;
  111. }
  112.  
  113. ISpUSBDevice::~ISpUSBDevice()
  114. {
  115.     if (mPatched) { Unpatch(); }
  116.     DisposeMapping();
  117.  
  118.     {
  119.         mHIDModuleDispatchTable = 0;            // lose the reference for sure
  120.  
  121.         ::USBRemoveDeviceNotification(mConnectionNotifyPB.token);
  122.     }
  123. }
  124.  
  125. void ISpUSBDevice::FinishConstruction(void)
  126. {
  127.     OSStatus err;
  128.     
  129.     short ref;
  130.     ref = FSpOpenResFile(&mFileSpec, fsRdPerm);
  131.     BuildMapping();
  132.     CloseResFile(ref);
  133.     
  134.     GetFeatures();
  135.  
  136.     for(UInt32 itr = 0; itr <= kDialogItem_NumPopups; itr++)
  137.         mDialogItemToNeedMapping[itr] = kUnsetIndex;
  138.     
  139.     ClearVirtuals ();
  140.     
  141.     err = Patch();
  142.     WARNING(err == noErr, "Patch failed in ISpUSBDevice::ISpUSBDevice");
  143.  
  144.     mActive = false;
  145.     SetActive (true);
  146. }
  147.  
  148. /* =============================================================================
  149.  *        Patch (private)
  150.  *
  151.  *    Installs the appropriate patch for this mouse.
  152.  * ========================================================================== */
  153. OSStatus ISpUSBDevice::Patch(void)
  154. {
  155.     WARNING(mPatched == false, "ISpUSBDevice Unpatch called but were are not patched!");
  156.  
  157.     OSStatus            err;    
  158.  
  159.     if (0 != mHIDModuleDispatchTable)
  160.     {
  161.         err = (*mHIDModuleDispatchTable->pUHIDClaimDevice)(&mUHIDConnectionID, 0);
  162.         WARNING(err == noErr, "USBDevice UHIDClaimDevice failed in Patch");
  163.  
  164.         if (err == noErr)
  165.         {
  166.             // Install our handler
  167.             err = (*mHIDModuleDispatchTable->pUHIDInstallInterrupt)(mUHIDConnectionID, MyUHIDInterruptProc, (UInt32) this);
  168.             WARNING(err == noErr, "USBDevice UHIDInstallInterrupt failed in Patch");
  169.         }
  170.     }
  171.  
  172.     // mark as patched
  173.     mPatched = true;
  174.  
  175.     return noErr;
  176. }
  177.  
  178.  
  179. /* =============================================================================
  180.  *        Unpatch (private)
  181.  *
  182.  *    Removes the patch that we installed for this mouse.
  183.  * ========================================================================== */
  184. OSStatus ISpUSBDevice::Unpatch(void)
  185. {
  186.     OSStatus    err = noErr;
  187.     
  188.     WARNING(mPatched == true, "ISpUSBDevice Unpatch called but were are not patched!");
  189.     
  190.     if (0 != mHIDModuleDispatchTable)
  191.     {
  192.         // Install our handler
  193.         err = (*mHIDModuleDispatchTable->pUHIDInstallInterrupt)(mUHIDConnectionID, nil, 0);
  194.         WARNING(err == noErr, "USBDevice UHIDInstallInterrupt failed in Unpatch");
  195.  
  196.         err = (*mHIDModuleDispatchTable->pUHIDReleaseDevice)(mUHIDConnectionID);
  197.         WARNING(err == noErr, "USBDevice UHIDReleaseDevice failed in Unpatch");
  198.     }
  199.  
  200.     // mark as unpatched
  201.     mPatched = false;        
  202.     
  203.     return err;
  204. }
  205.  
  206. /* =============================================================================
  207.  *        MyUHIDInterruptProc (local, c)
  208.  *
  209.  *    This routine is called by the UHIDModule when there is an interupt packet.
  210.  * ========================================================================== */
  211. void MyUHIDInterruptProc (void *theData, UInt32 refcon)
  212. {
  213.     ISpUSBDevice* usbDeviceProCore = (ISpUSBDevice*) refcon;
  214.     WARNING(usbDeviceProCore != nil, "USBDevice: patch object pointer was null");
  215.  
  216.     if (usbDeviceProCore != nil)
  217.         { usbDeviceProCore->ParseData((Ptr)theData); }
  218. }
  219.  
  220. inline void ISpUSBDevice::HandleDisappearedDevice(USBDeviceNotificationParameterBlockPtr passedPB)
  221. {
  222. #pragma unused ( passedPB )
  223.     if (this->mUSBDeviceRef == passedPB->usbDeviceRef)
  224.         this->mHIDModuleDispatchTable = 0;        // remove references to now gone device
  225. }
  226.  
  227. /* =============================================================================
  228.  *        UIDNotifyProc
  229.  *
  230.  *    This routine is called by the the USB manager when we get a notify callback.
  231.  * ========================================================================== */
  232. void ISpUSBDevice::UIDNotifyProc(USBDeviceNotificationParameterBlockPtr passedPB)
  233. {
  234.     ISpUSBDevice*    usbDeviceProCore = (ISpUSBDevice*) passedPB->refcon;
  235.     WARNING(usbDeviceProCore != nil, "USBDevice: notify object pointer was null");
  236.  
  237. // We must check the type of callback since even though we only registered for driver gone callbacks.
  238. // This is due to Radar bug #2248893.
  239.  
  240.     if (0 != usbDeviceProCore &&
  241.         kNotifyRemoveInterface == passedPB->usbDeviceNotification)                    // our device removed
  242.     {
  243.         usbDeviceProCore->HandleDisappearedDevice(passedPB);
  244.     }
  245. }
  246.  
  247. OSStatus ISpUSBDevice::Init(UInt32 count, ISpNeed needs[], ISpElementReference virtualElements[], 
  248.                 Boolean used[], OSType appCreatorCode, OSType subCreatorCode, 
  249.                 UInt32 reserved, void* reserved2)
  250. {
  251. // dont use these four
  252. #pragma unused (appCreatorCode)
  253. #pragma unused (subCreatorCode)
  254. #pragma unused (reserved)
  255. #pragma unused (reserved2)
  256.     
  257.     UInt32 itr;
  258.  
  259.     // allocate arrays to hold references and needs and copy the data in
  260.     mReferences = (ISpElementReference *) NewPtrSysClear(count * sizeof(ISpElementReference));
  261.     WARNING(mReferences != nil,    "ISpUSBDevice::Init failed to allocate mReferences");
  262.     if (mReferences == nil) { return -1; }
  263.  
  264.     mNeeds = (ISpNeed *) NewPtrSysClear(count * sizeof(ISpNeed));
  265.     WARNING(mNeeds != nil,        "ISpUSBDevice::Init failed to allocate mNeeds");
  266.     if (mNeeds == nil)
  267.     {
  268.         DisposePtr((Ptr) mReferences);
  269.         mReferences = nil;
  270.         return - 1;
  271.     }
  272.  
  273.     mNumNeeds = count;
  274.  
  275.     // copy the data
  276.     for(itr = 0; itr < count; itr++)
  277.     {
  278.         mReferences[itr] = virtualElements[itr];
  279.         mNeeds[itr] = needs[itr];
  280.     }
  281.     
  282.     // zero high level data
  283.     mCurHLData.xAxis = mCurHLData.yAxis = mCurHLData.rudder = kISpAxisMiddle;                        // symetric axis
  284.     mCurHLData.trim = mCurHLData.throttle = kISpAxisMiddle; // (since we allow buttons for both ends)
  285.     mCurHLData.brake = mCurHLData.gas = kISpAxisMinimum;    // asymetric axis
  286.     for (UInt32 button_itr = 0; button_itr < kMaxHighLevelButtons; button_itr++)
  287.         mCurHLData.buttons[button_itr] = kISpButtonUp;
  288.     for (UInt32 dpad_itr = 0; dpad_itr < kMaxHighLevelDpads; dpad_itr++)
  289.         mCurHLData.dpads[dpad_itr] = kISpPadIdle;
  290.     SetAsFields (mCurHLData);
  291.     mOldHLData = mCurHLData;
  292.  
  293.     AutoConfigure(used);    // sets mDialogItemToNeedMapping and the virtual elements
  294.  
  295.     mVirtualElementsValid = true;
  296.     mDirty = false;     
  297.  
  298.     // set initial values
  299.     SetAsFields (mOldHLData);
  300.     PushDataToVirtuals (mOldHLData);
  301.         
  302.     return noErr;
  303. }
  304.  
  305. void ISpUSBDevice::AutoConfigure(Boolean used[])
  306. {
  307.     // mVirtualElement might not be valid yet
  308.     WARNING(mNeeds != nil,                        "ISpUSBDevice::AutoConfigure mNeeds was nil");
  309.     WARNING(used != nil,                        "ISpUSBDevice::AutoConfigure used was nil");
  310.     WARNING(mDialogItemToNeedMapping != nil,    "ISpUSBDevice::AutoConfigure mDialogItemToNeepMapping was nil");
  311.     
  312.     // clear out all the entries
  313.     UInt32 itr;
  314.     for(itr = 0; itr <= kDialogItem_NumPopups; itr++)
  315.         { mDialogItemToNeedMapping[itr] = kUnsetIndex; }
  316.  
  317.     // AutoConfigure reads from mNeeds, mNumNeeds and sets mDialogItemToNeedMapping
  318.     
  319.     // we use this array to track which needs we've assigned (we handle case where this fails)
  320.     Boolean * assigned = (Boolean *) NewPtrSysClear (mNumNeeds * sizeof(Boolean));
  321.     
  322.     // only make one pass if we failed to allocate assigned array
  323.     UInt32 numPasses;
  324.     numPasses = (assigned == nil) ? 1 : 2;
  325.     
  326.     // we'll do a two pass method, the first pass we'll only assign exact matches
  327.     // the second pass we'll assign things that are close
  328.     UInt32 pass;
  329.     for (pass = 1; pass <= numPasses; pass++)
  330.     {
  331.         Boolean    onlyExactMatches = true;
  332.         if (pass == numPasses)    // don't need exact match if last pass
  333.             onlyExactMatches = false;
  334.     
  335.         for (UInt32 itr = 0; itr < mNumNeeds; itr++)
  336.         {
  337.             Boolean    configured = false;
  338.             
  339.             // skip this need if we assigned it in the last pass
  340.             if (assigned != nil)
  341.                 if (assigned[itr])
  342.                     continue;
  343.  
  344.             // we don't autoconfig to utility needs
  345.             if (mNeeds[itr].flags & kISpNeedFlag_Utility)
  346.                 continue;
  347.             
  348.             if (used[itr] && (mNeeds[itr].flags & kISpNeedFlag_NoMultiConfig))
  349.                 continue;
  350.             
  351.             switch(mNeeds[itr].theKind)
  352.             {
  353.                 case kISpElementKind_Button:
  354.                     if (TryButtonConfig (itr, onlyExactMatches))
  355.                         configured = true;
  356.                     break;
  357.                 
  358.                 case kISpElementKind_Axis:
  359.                     if (TryAxisConfig (itr, onlyExactMatches))
  360.                         configured = true;
  361.                     break;
  362.                     
  363.                 case kISpElementKind_DPad:
  364.                     if (TryDPadConfig (itr, onlyExactMatches))
  365.                         configured = true;
  366.                     else if (!onlyExactMatches)
  367.                     {
  368.                         if (TryStickConfig (itr, onlyExactMatches))
  369.                             configured = true;
  370.                     }
  371.                     break;
  372.                         
  373.                 case kISpElementKind_Movement:
  374.                     if (TryStickConfig (itr, onlyExactMatches))
  375.                         configured = true;
  376.                     else if (!onlyExactMatches)
  377.                     {
  378.                         if (TryDPadConfig (itr, onlyExactMatches))
  379.                             configured = true;
  380.                     }
  381.                     break;
  382.             }
  383.         
  384.             if (configured)
  385.             {
  386.                 if (assigned != nil)
  387.                     assigned[itr] = true;
  388.                 
  389.                 used[itr] = true;
  390.             }
  391.  
  392.         }
  393.     }
  394.     
  395.     if (assigned != nil)
  396.         DisposePtr((Ptr) assigned);
  397.  
  398.     // assign the high level level elements
  399.     SetVirtualElements ();
  400. }
  401.  
  402. Boolean    ISpUSBDevice::TryButtonConfig (UInt32 inNeedIndex, Boolean inOnlyExactMatch)
  403. {
  404.     Boolean configured = false;
  405.     
  406.     switch(mNeeds[inNeedIndex].theLabel)
  407.     {
  408.         case kISpElementLabel_Btn_SlideLeft:
  409.         case kISpElementLabel_Btn_LookLeft:
  410.         case kISpElementLabel_Btn_TurnLeft:
  411.             if (!inOnlyExactMatch && features.hasXAxis &&
  412.                 mDialogItemToNeedMapping[kDialogItem_StickLeft] == kUnsetIndex)
  413.             {
  414.                 configured = true;
  415.                 mDialogItemToNeedMapping[kDialogItem_StickLeft] = inNeedIndex;
  416.             }
  417.             break;
  418.             
  419.         case kISpElementLabel_Btn_SlideRight:
  420.         case kISpElementLabel_Btn_TurnRight:
  421.         case kISpElementLabel_Btn_LookRight:
  422.             if (!inOnlyExactMatch && features.hasXAxis &&
  423.                 mDialogItemToNeedMapping[kDialogItem_StickRight] == kUnsetIndex)
  424.             {
  425.                 configured = true;
  426.                 mDialogItemToNeedMapping[kDialogItem_StickRight] = inNeedIndex;
  427.             }
  428.             break;
  429.             
  430.         case kISpElementLabel_Btn_MoveForward:
  431.         case kISpElementLabel_Btn_LookUp:
  432.             if (!inOnlyExactMatch && features.hasYAxis &&
  433.                 mDialogItemToNeedMapping[kDialogItem_StickUp] == kUnsetIndex)
  434.             {
  435.                 configured = true;
  436.                 mDialogItemToNeedMapping[kDialogItem_StickUp] = inNeedIndex;
  437.             }
  438.             break;
  439.             
  440.         case kISpElementLabel_Btn_MoveBackward:
  441.         case kISpElementLabel_Btn_LookDown:
  442.             if (!inOnlyExactMatch && features.hasYAxis &&
  443.                 mDialogItemToNeedMapping[kDialogItem_StickDown] == kUnsetIndex)
  444.             {
  445.                 configured = true;
  446.                 mDialogItemToNeedMapping[kDialogItem_StickDown] = inNeedIndex;
  447.             }
  448.             break;
  449.             
  450.         case kISpElementLabel_Btn_Fire:
  451.             if (features.triggerButtonIndex != kUnsetIndex &&
  452.                 mDialogItemToNeedMapping[kDialogItem_Button1 + features.triggerButtonIndex] == kUnsetIndex)
  453.             {
  454.                 configured = true;
  455.                 mDialogItemToNeedMapping[kDialogItem_Button1 + features.triggerButtonIndex] = inNeedIndex;
  456.             }
  457.             break;
  458.  
  459.         case kISpElementLabel_Btn_PauseResume:
  460.             if (features.startButtonIndex != kUnsetIndex &&
  461.                 mDialogItemToNeedMapping[kDialogItem_Button1 + features.startButtonIndex] == kUnsetIndex)
  462.             {
  463.                 configured = true;
  464.                 mDialogItemToNeedMapping[kDialogItem_Button1 + features.startButtonIndex] = inNeedIndex;
  465.             }
  466.             break;
  467.             
  468.         case kISpElementLabel_Btn_Select:
  469.             if (features.selectButtonIndex != kUnsetIndex &&
  470.                 mDialogItemToNeedMapping[kDialogItem_Button1 + features.selectButtonIndex] == kUnsetIndex)
  471.             {
  472.                 configured = true;
  473.                 mDialogItemToNeedMapping[kDialogItem_Button1 + features.selectButtonIndex] = inNeedIndex;
  474.             }
  475.             break;
  476.  
  477.         default:
  478.             // we handle this case below
  479.             break;
  480.         }
  481.     
  482.     // if unconfigured, and not exact match, we just map to any unassigned button
  483.     if (!configured && !inOnlyExactMatch)
  484.         // don't configure axis or delta versions of buttons that did not have direction set...
  485.         // they probably don't make sense for autoconfiguring
  486.         if (!(mNeeds[inNeedIndex].flags & kISpNeedFlag_Button_AlreadyDelta) &&
  487.             !(mNeeds[inNeedIndex].flags & kISpNeedFlag_Button_AlreadyAxis) )
  488.         {
  489.             UInt32 orderedIndex, buttonIndex;
  490.             
  491.             // first try to match ordered buttons
  492.             for (orderedIndex = 0; orderedIndex < mNumOrderedButtons && !configured; orderedIndex++)
  493.             {
  494.                 buttonIndex = mOrderedButtonsIndecies[orderedIndex];
  495.                 
  496.                 if (mDialogItemToNeedMapping[kDialogItem_Button1 + buttonIndex] == kUnsetIndex)
  497.                 {
  498.                     configured = true;
  499.                     mDialogItemToNeedMapping[kDialogItem_Button1 + buttonIndex] = inNeedIndex;
  500.                 }
  501.             }
  502.             
  503.             // now match anything
  504.             for (buttonIndex = 0; buttonIndex < features.numButtons && !configured; buttonIndex++)
  505.             {
  506.                 if (mDialogItemToNeedMapping[kDialogItem_Button1 + buttonIndex] == kUnsetIndex)
  507.                 {
  508.                     configured = true;
  509.                     mDialogItemToNeedMapping[kDialogItem_Button1 + buttonIndex] = inNeedIndex;
  510.                 }
  511.             }
  512.         }
  513.  
  514.     return configured;
  515. }
  516.  
  517. Boolean    ISpUSBDevice::TryAxisConfig (UInt32 inNeedIndex, Boolean inOnlyExactMatch)
  518. {
  519.     Boolean configured = false;
  520.  
  521.     switch (mNeeds[inNeedIndex].theLabel)
  522.     {
  523.         case kISpElementLabel_Axis_Rz:
  524.         case kISpElementLabel_Axis_XAxis:
  525.             if (TryStickXAxisConfig (inNeedIndex))
  526.                 configured = true;
  527.             else if (!inOnlyExactMatch)
  528.             {
  529.                 if (TryRudderConfig (inNeedIndex))
  530.                     configured = true;
  531.                 else if (TryDPadXAxisConfig (inNeedIndex))
  532.                     configured = true;
  533.             }
  534.             break;
  535.             
  536.         case kISpElementLabel_Axis_Rx:
  537.         case kISpElementLabel_Axis_YAxis:
  538.             if (TryStickYAxisConfig (inNeedIndex))
  539.                 configured = true;
  540.             else if (!inOnlyExactMatch)
  541.             {
  542.                 if (TryTrimConfig (inNeedIndex))
  543.                     configured = true;
  544.                 else if (TryDPadYAxisConfig (inNeedIndex))
  545.                     configured = true;
  546.             }
  547.             break;
  548.  
  549.         case kISpElementLabel_Axis_ZAxis:
  550.             if (!inOnlyExactMatch)
  551.             {
  552.                 if (TryTrimConfig (inNeedIndex))
  553.                     configured = true;
  554.                 else if (TryStickYAxisConfig (inNeedIndex))
  555.                     configured = true;
  556.                 else if (TryDPadYAxisConfig (inNeedIndex))
  557.                     configured = true;
  558.             }
  559.             break;
  560.  
  561.         case kISpElementLabel_Axis_Throttle:
  562.             if (TryThrottleConfig (inNeedIndex))
  563.                 configured = true;
  564.             else if (!inOnlyExactMatch)
  565.             {
  566.                 if (TryTrimConfig (inNeedIndex))
  567.                     configured = true;
  568.                 else if (TryDPadYAxisConfig (inNeedIndex))
  569.                     configured = true;
  570.             }
  571.             break;
  572.             
  573.         case kISpElementLabel_Axis_Trim:
  574.             if (TryTrimConfig (inNeedIndex))
  575.                 configured = true;
  576.             else if (!inOnlyExactMatch)
  577.             {
  578.                 if (TryDPadYAxisConfig (inNeedIndex))
  579.                     configured = true;
  580.             }
  581.             break;
  582.             
  583.         case kISpElementLabel_Axis_Ry:
  584.         case kISpElementLabel_Axis_Rudder:
  585.             if (TryRudderConfig (inNeedIndex))
  586.                 configured = true;
  587.             else if (!inOnlyExactMatch)
  588.             {
  589.                 if (TryStickXAxisConfig (inNeedIndex))
  590.                     configured = true;
  591.                 else if (TryDPadXAxisConfig (inNeedIndex))
  592.                     configured = true;
  593.             }
  594.             break;
  595.         
  596.         case kISpElementLabel_Axis_Gas:
  597.             if (TryGasConfig (inNeedIndex))
  598.                 configured = true;
  599.             else if (!inOnlyExactMatch)
  600.             {
  601.                 if (TryThrottleConfig (inNeedIndex))
  602.                     configured = true;
  603.             }
  604.             break;
  605.             
  606.         case kISpElementLabel_Axis_Brake:
  607.             if (TryBrakeConfig (inNeedIndex))
  608.                 configured = true;
  609.             break;
  610.             
  611.     }
  612.     
  613.     return configured;
  614. }
  615.  
  616. Boolean    ISpUSBDevice::TryDPadConfig (UInt32 inNeedIndex, Boolean inOnlyExactMatch)
  617. {
  618.     inOnlyExactMatch;        // not used (we only check for exact matches
  619.     
  620.     Boolean configured = false;
  621.     
  622.     // we make to passes, so as to prefer 8-way hats
  623.     for (UInt32 pass = 1; pass <= 2; pass++)
  624.         for (UInt32 dpadIndex = 0; dpadIndex < features.numDPads && !configured; dpadIndex++)
  625.         {
  626.             // on first pass, only configure 8-way hats
  627.             if ((!features.is4WayDPad[dpadIndex] || pass == 2) &&
  628.                 (mDialogItemToNeedMapping[kDialogItem_DPad1Up + (dpadIndex * 4)] == kUnsetIndex) &&
  629.                 (mDialogItemToNeedMapping[kDialogItem_DPad1Left + (dpadIndex * 4)] == kUnsetIndex) &&
  630.                 (mDialogItemToNeedMapping[kDialogItem_DPad1Down + (dpadIndex * 4)] == kUnsetIndex) &&
  631.                 (mDialogItemToNeedMapping[kDialogItem_DPad1Right + (dpadIndex * 4)] == kUnsetIndex))
  632.             {
  633.                 configured = true;
  634.                 
  635.                 mDialogItemToNeedMapping[kDialogItem_DPad1Up + (dpadIndex * 4)] = inNeedIndex;
  636.                 mDialogItemToNeedMapping[kDialogItem_DPad1Left + (dpadIndex * 4)] = inNeedIndex;
  637.                 mDialogItemToNeedMapping[kDialogItem_DPad1Down + (dpadIndex * 4)] = inNeedIndex;
  638.                 mDialogItemToNeedMapping[kDialogItem_DPad1Right + (dpadIndex * 4)] = inNeedIndex;
  639.             }
  640.         }
  641.     
  642.     return configured;
  643. }
  644.  
  645. Boolean    ISpUSBDevice::TryStickConfig (UInt32 inNeedIndex, Boolean inOnlyExactMatch)
  646. {
  647.     inOnlyExactMatch;        // not used (we only check for exact matches
  648.  
  649.     Boolean configured = false;
  650.  
  651.     if (features.hasXAxis && features.hasYAxis &&
  652.         (mDialogItemToNeedMapping[kDialogItem_StickUp] == kUnsetIndex) &&
  653.         (mDialogItemToNeedMapping[kDialogItem_StickDown] == kUnsetIndex) &&
  654.         (mDialogItemToNeedMapping[kDialogItem_StickLeft] == kUnsetIndex) &&
  655.         (mDialogItemToNeedMapping[kDialogItem_StickRight] == kUnsetIndex))
  656.     {
  657.         configured = true;
  658.         
  659.         mDialogItemToNeedMapping[kDialogItem_StickUp] = inNeedIndex;
  660.         mDialogItemToNeedMapping[kDialogItem_StickLeft] = inNeedIndex;
  661.         mDialogItemToNeedMapping[kDialogItem_StickDown] = inNeedIndex;
  662.         mDialogItemToNeedMapping[kDialogItem_StickRight] = inNeedIndex;
  663.     }
  664.  
  665.     return configured;
  666. }
  667.  
  668. Boolean    ISpUSBDevice::TryStickXAxisConfig (UInt32 inNeedIndex)
  669. {
  670.     Boolean configured = false;
  671.  
  672.     if (features.hasXAxis && 
  673.         (mDialogItemToNeedMapping[kDialogItem_StickLeft] == kUnsetIndex) &&
  674.         (mDialogItemToNeedMapping[kDialogItem_StickRight] == kUnsetIndex))
  675.     {
  676.         configured = true;
  677.         
  678.         mDialogItemToNeedMapping[kDialogItem_StickLeft] = inNeedIndex;
  679.         mDialogItemToNeedMapping[kDialogItem_StickRight] = inNeedIndex;
  680.     }
  681.  
  682.     return configured;
  683.  
  684. }
  685.  
  686. Boolean    ISpUSBDevice::TryStickYAxisConfig (UInt32 inNeedIndex)
  687. {
  688.     Boolean configured = false;
  689.  
  690.     if (features.hasYAxis &&
  691.         (mDialogItemToNeedMapping[kDialogItem_StickUp] == kUnsetIndex) &&
  692.         (mDialogItemToNeedMapping[kDialogItem_StickDown] == kUnsetIndex))
  693.     {
  694.         configured = true;
  695.         
  696.         mDialogItemToNeedMapping[kDialogItem_StickUp] = inNeedIndex;
  697.         mDialogItemToNeedMapping[kDialogItem_StickDown] = inNeedIndex;
  698.     }
  699.  
  700.     return configured;
  701.  
  702. }
  703.  
  704. Boolean    ISpUSBDevice::TryDPadXAxisConfig (UInt32 inNeedIndex)
  705. {
  706.     Boolean configured = false;
  707.  
  708.     for (UInt32 dpadIndex = 0; dpadIndex < features.numDPads && !configured; dpadIndex++)
  709.     {
  710.         if ((mDialogItemToNeedMapping[kDialogItem_DPad1Left + (dpadIndex * 4)] == kUnsetIndex) &&
  711.             (mDialogItemToNeedMapping[kDialogItem_DPad1Right + (dpadIndex * 4)] == kUnsetIndex))
  712.         {
  713.             configured = true;
  714.             
  715.             mDialogItemToNeedMapping[kDialogItem_DPad1Left + (dpadIndex * 4)] = inNeedIndex;
  716.             mDialogItemToNeedMapping[kDialogItem_DPad1Right + (dpadIndex * 4)] = inNeedIndex;
  717.         }
  718.     }
  719.  
  720.     return configured;
  721. }
  722.  
  723. Boolean    ISpUSBDevice::TryDPadYAxisConfig (UInt32 inNeedIndex)
  724. {
  725.     Boolean configured = false;
  726.  
  727.     for (UInt32 dpadIndex = 0; dpadIndex < features.numDPads && !configured; dpadIndex++)
  728.     {
  729.         if ((mDialogItemToNeedMapping[kDialogItem_DPad1Up + (dpadIndex * 4)] == kUnsetIndex) &&
  730.             (mDialogItemToNeedMapping[kDialogItem_DPad1Down + (dpadIndex * 4)] == kUnsetIndex))
  731.         {
  732.             configured = true;
  733.             
  734.             mDialogItemToNeedMapping[kDialogItem_DPad1Up + (dpadIndex * 4)] = inNeedIndex;
  735.             mDialogItemToNeedMapping[kDialogItem_DPad1Down + (dpadIndex * 4)] = inNeedIndex;
  736.         }
  737.     }
  738.  
  739.     return configured;
  740. }
  741.  
  742. Boolean    ISpUSBDevice::TryTrimConfig (UInt32 inNeedIndex)
  743. {
  744.     Boolean configured = false;
  745.  
  746.     if (features.hasTrim &&
  747.         (mDialogItemToNeedMapping[kDialogItem_TrimHigher] == kUnsetIndex) &&
  748.         (mDialogItemToNeedMapping[kDialogItem_TrimLower] == kUnsetIndex))
  749.     {
  750.         configured = true;
  751.         
  752.         mDialogItemToNeedMapping[kDialogItem_TrimHigher] = inNeedIndex;
  753.         mDialogItemToNeedMapping[kDialogItem_TrimLower] = inNeedIndex;
  754.     }
  755.  
  756.     return configured;
  757. }
  758.  
  759. Boolean    ISpUSBDevice::TryThrottleConfig (UInt32 inNeedIndex)
  760. {
  761.     Boolean configured = false;
  762.  
  763.     if (features.hasThrottle &&
  764.         (mDialogItemToNeedMapping[kDialogItem_ThrottleHigher] == kUnsetIndex) &&
  765.         (mDialogItemToNeedMapping[kDialogItem_ThrottleLower] == kUnsetIndex))
  766.     {
  767.         configured = true;
  768.         
  769.         mDialogItemToNeedMapping[kDialogItem_ThrottleHigher] = inNeedIndex;
  770.         mDialogItemToNeedMapping[kDialogItem_ThrottleLower] = inNeedIndex;
  771.     }
  772.  
  773.     return configured;
  774. }
  775.  
  776. Boolean    ISpUSBDevice::TryRudderConfig (UInt32 inNeedIndex)
  777. {
  778.     Boolean configured = false;
  779.  
  780.     if (features.hasRudder &&
  781.         (mDialogItemToNeedMapping[kDialogItem_RudderLeft] == kUnsetIndex) &&
  782.         (mDialogItemToNeedMapping[kDialogItem_RudderRight] == kUnsetIndex))
  783.     {
  784.         configured = true;
  785.         
  786.         mDialogItemToNeedMapping[kDialogItem_RudderLeft] = inNeedIndex;
  787.         mDialogItemToNeedMapping[kDialogItem_RudderRight] = inNeedIndex;
  788.     }
  789.  
  790.     return configured;
  791. }
  792.  
  793. Boolean    ISpUSBDevice::TryGasConfig (UInt32 inNeedIndex)
  794. {
  795.     Boolean configured = false;
  796.  
  797.     if (features.hasGas &&
  798.         mDialogItemToNeedMapping[kDialogItem_GasDepressed] == kUnsetIndex)
  799.     {
  800.         configured = true;
  801.         
  802.         mDialogItemToNeedMapping[kDialogItem_GasDepressed] = inNeedIndex;
  803.     }
  804.  
  805.     return configured;
  806. }
  807.  
  808. Boolean    ISpUSBDevice::TryBrakeConfig (UInt32 inNeedIndex)
  809. {
  810.     Boolean configured = false;
  811.  
  812.     if (features.hasBrake &&
  813.         mDialogItemToNeedMapping[kDialogItem_BrakeDepressed] == kUnsetIndex)
  814.     {
  815.         configured = true;
  816.         
  817.         mDialogItemToNeedMapping[kDialogItem_BrakeDepressed] = inNeedIndex;
  818.     }
  819.  
  820.     return configured;
  821. }
  822.  
  823. OSStatus ISpUSBDevice::Stop(void)
  824. {
  825.     // need to mark mVirtualElementValid as false first
  826.     mVirtualElementsValid = false;
  827.  
  828.     if (mReferences)  DisposePtr((Ptr) mReferences);    
  829.     mReferences = nil;
  830.     
  831.     if (mNeeds) DisposePtr((Ptr) mNeeds);    
  832.     mNeeds = nil;
  833.     
  834.     return noErr;
  835. }
  836.  
  837. OSStatus ISpUSBDevice::HandleEvent(EventRecord &theEvent, Boolean &handled)
  838. {
  839.     theEvent;
  840.     
  841.     handled = false;
  842.         
  843.     UpdateAllButtons();
  844.  
  845.     return noErr;
  846. }
  847.  
  848. OSStatus ISpUSBDevice::Show(DialogPtr theDialog, short dialogItemNumber, Rect &r)
  849. {
  850.     mRect = r;
  851.     
  852.     mBaseDITLCount = CountDITL(theDialog);
  853.     mResRef = FSpOpenResFile(&mFileSpec, fsRdPerm);
  854.     RES_WARNING("\pcould not FSpOpenResFile on the Joy ResFile");
  855.     
  856.     Handle ditl = Get1Resource('DITL', GetDeviceResID());
  857.     RES_WARNING("\pcould not Get1Resource on the Joy DITL");
  858.     
  859.     mDialog = theDialog;
  860.     mVisable = true;
  861.  
  862.     AppendDITL(theDialog, ditl, -dialogItemNumber);
  863.     ReleaseResource(ditl);
  864.  
  865.     // x & y axis
  866.     if (!features.hasXAxis)
  867.     {
  868.         MakeDialogItemInvisable (theDialog, kDialogItem_StickLeft + mBaseDITLCount);
  869.         MakeDialogItemInvisable (theDialog, kDialogItem_StickRight + mBaseDITLCount);
  870.         if (!features.hasYAxis)
  871.             MakeDialogItemInvisable (theDialog, kDialogItem_Stick_Label + mBaseDITLCount);
  872.     }
  873.     if (!features.hasYAxis)
  874.     {
  875.         MakeDialogItemInvisable (theDialog, kDialogItem_StickUp + mBaseDITLCount);
  876.         MakeDialogItemInvisable (theDialog, kDialogItem_StickDown + mBaseDITLCount);
  877.         MakeDialogItemInvisable (theDialog, kDialogItem_ReverseStick + mBaseDITLCount);
  878.     }
  879.     else
  880.         SetDialogControl(kDialogItem_ReverseStick,    mReverseStick);
  881.     
  882.     // trim
  883.     if (!features.hasTrim)
  884.     {
  885.         MakeDialogItemInvisable (theDialog, kDialogItem_TrimLower + mBaseDITLCount);
  886.         MakeDialogItemInvisable (theDialog, kDialogItem_TrimHigher + mBaseDITLCount);
  887.         MakeDialogItemInvisable (theDialog, kDialogItem_Trim_Label + mBaseDITLCount);
  888.         MakeDialogItemInvisable (theDialog, kDialogItem_ReverseTrim + mBaseDITLCount);
  889.     }
  890.     else
  891.         SetDialogControl(kDialogItem_ReverseTrim,    mReverseTrim);
  892.     
  893.     // throttle
  894.     if (!features.hasThrottle)
  895.     {
  896.         MakeDialogItemInvisable (theDialog, kDialogItem_ThrottleLower + mBaseDITLCount);
  897.         MakeDialogItemInvisable (theDialog, kDialogItem_ThrottleHigher + mBaseDITLCount);
  898.         MakeDialogItemInvisable (theDialog, kDialogItem_Throttle_Label + mBaseDITLCount);
  899.         MakeDialogItemInvisable (theDialog, kDialogItem_ReverseThrottle + mBaseDITLCount);
  900.     }
  901.     else
  902.         SetDialogControl(kDialogItem_ReverseThrottle,    mReverseThrottle);
  903.     
  904.     // rudder
  905.     if (!features.hasRudder)
  906.     {
  907.         MakeDialogItemInvisable (theDialog, kDialogItem_RudderLeft + mBaseDITLCount);
  908.         MakeDialogItemInvisable (theDialog, kDialogItem_RudderRight + mBaseDITLCount);
  909.         MakeDialogItemInvisable (theDialog, kDialogItem_Rudder_Label + mBaseDITLCount);
  910.         MakeDialogItemInvisable (theDialog, kDialogItem_ReverseRudder + mBaseDITLCount);
  911.     }
  912.     else
  913.         SetDialogControl(kDialogItem_ReverseRudder,    mReverseRudder);
  914.  
  915.     // brake
  916.     if (!features.hasBrake)
  917.     {
  918.         MakeDialogItemInvisable (theDialog, kDialogItem_BrakeDepressed + mBaseDITLCount);
  919.         MakeDialogItemInvisable (theDialog, kDialogItem_Brake_Label + mBaseDITLCount);
  920.     }
  921.     // obsolete ditem
  922.     MakeDialogItemInvisable (theDialog, kDialogItem_BrakeNotUsed + mBaseDITLCount);
  923.     
  924.     // gas
  925.     if (!features.hasGas)
  926.     {
  927.         MakeDialogItemInvisable (theDialog, kDialogItem_GasDepressed + mBaseDITLCount);
  928.         MakeDialogItemInvisable (theDialog, kDialogItem_Gas_Label + mBaseDITLCount);
  929.     }
  930.     // obsolete ditem
  931.     MakeDialogItemInvisable (theDialog, kDialogItem_GasNotUsed + mBaseDITLCount);
  932.     
  933.     // buttons
  934.     if (features.numButtons < kMaxHighLevelButtons )
  935.     {
  936.         UInt32 buttonsToRemove = kMaxHighLevelButtons - features.numButtons;
  937.         while (buttonsToRemove--)
  938.             MakeDialogItemInvisable (theDialog, kDialogItem_Button12 - buttonsToRemove + mBaseDITLCount);
  939.         
  940.         if (features.numButtons == 0)
  941.             MakeDialogItemInvisable (theDialog, kDialogItem_Buttons_Label + mBaseDITLCount);
  942.     }
  943.  
  944.     // dpads
  945.     if (features.numDPads < kMaxHighLevelDpads )
  946.     {
  947.         UInt32 itemsToRemove = kMaxHighLevelDpads - features.numDPads;
  948.         while (itemsToRemove--)
  949.         {
  950.             MakeDialogItemInvisable (theDialog, kDialogItem_DPad4Up - (itemsToRemove * 4) + mBaseDITLCount);
  951.             MakeDialogItemInvisable (theDialog, kDialogItem_DPad4Left - (itemsToRemove * 4) + mBaseDITLCount);
  952.             MakeDialogItemInvisable (theDialog, kDialogItem_DPad4Down - (itemsToRemove * 4) + mBaseDITLCount);
  953.             MakeDialogItemInvisable (theDialog, kDialogItem_DPad4Right - (itemsToRemove * 4) + mBaseDITLCount);
  954.             
  955.             MakeDialogItemInvisable (theDialog, kDialogItem_ReverseDPad4 - itemsToRemove + mBaseDITLCount);
  956.         }
  957.         
  958.         if (features.numDPads == 0)
  959.             MakeDialogItemInvisable (theDialog, kDialogItem_DPads_Label + mBaseDITLCount);
  960.     }
  961.     
  962.     UInt32 index;
  963.     for (index = 0; index < features.numDPads; index++)
  964.         SetDialogControl(kDialogItem_ReverseDPad1 + index,    mReverseDPad[index]);
  965.     
  966.     // clear out ui indiciators
  967.     for (index = 0; index < kDialogItem_NumPopups; index++)
  968.         mPopupPressed[index] = false;
  969.     UpdateAllButtons ();
  970.     
  971.     return noErr;
  972. }
  973.  
  974. OSStatus ISpUSBDevice::Hide(void)
  975. {
  976.     // restore to original count of items
  977.     ShortenDITL(mDialog, CountDITL(mDialog) - mBaseDITLCount);
  978.     WARNING(CountDITL(mDialog) == mBaseDITLCount, "ISpUSBDevice::Hide Failed to restore the DITL count");
  979.     
  980.     // mark that we are no longer visable
  981.     mVisable = false;
  982.  
  983.     // clear our mDialog ptr
  984.     mDialog = nil;
  985.  
  986.     // close our res file and assert check
  987.     CloseResFile(mResRef);
  988.     RES_WARNING("ISpUSBDevice::Hide CloseResFile choked");
  989.     
  990.     return noErr;
  991. }
  992.  
  993. OSStatus ISpUSBDevice::BeginConfiguration(UInt32 count, ISpNeed needs[])
  994. {
  995. #pragma unused(count)
  996. #pragma unused(needs)
  997.  
  998.     WARNING(mVirtualElementsValid,        "BeginConfiguration was called but the virtual elements were not valid");
  999.  
  1000.     return noErr;
  1001. }
  1002.  
  1003. OSStatus ISpUSBDevice::EndConfiguration(Boolean accept)
  1004. {
  1005.     accept;
  1006.  
  1007.     WARNING(mVirtualElementsValid,        "EndConfiguration was called but the virtual elements were not valid");
  1008.  
  1009.     SetVirtualElements();    
  1010.     
  1011.     return noErr;
  1012. }
  1013.  
  1014. OSStatus ISpUSBDevice::SetActive(Boolean active)
  1015. {
  1016.     if (mActive == active) return noErr;
  1017.     
  1018.     mActive = active;
  1019.     
  1020.     // we're responsible for pushing any values which are non-default
  1021.     if (mActive) PushAllNonDefaultValues();
  1022.     
  1023.     return noErr;
  1024. }
  1025.  
  1026. /* =============================================================================
  1027.  *        PushAllNonDefaultValues (private)
  1028.  *
  1029.  *    This is done when activating, as part of our duties as the driver. 
  1030.  *
  1031.  *    A driver is responsible for pushing all non-default values when it is
  1032.  *    activated.
  1033.  *
  1034.  *    the default values for buttons, dpads, deltas and asymmetric axis is zero
  1035.  *    the default value for symmetric axis is kISpAxisMiddle
  1036.  *
  1037.  * ========================================================================== */
  1038. OSStatus ISpUSBDevice::PushAllNonDefaultValues(void)
  1039. {
  1040.     OSStatus err = noErr;
  1041.     AbsoluteTime time = ISpUptime ();
  1042.  
  1043.     // set all the 'old' values for axis elements to the reset value
  1044.     for (UInt32 itr = 0; itr < mUSBElementCount; itr++)
  1045.     {
  1046.         // if this is a valid axis then read the data
  1047.         if ((mUSBMapping[itr].kind == kISpElementKind_Axis) && (mUSBMapping[itr].valid))
  1048.         {
  1049.             UInt32        resetAxisValue = kISpAxisMinimum;
  1050.             if (mUSBMapping[itr].flags & kMappingFlag_AxisIsSymmetric)
  1051.                 resetAxisValue = kISpAxisMiddle;
  1052.             
  1053.             mUSBMapping[itr].lastValue = resetAxisValue;
  1054.  
  1055.             err = ISpElement_PushSimpleData(mUSBMapping[itr].element, resetAxisValue, &time);
  1056.         }
  1057.     }
  1058.     
  1059.     return noErr;
  1060. }
  1061.  
  1062. OSStatus ISpUSBDevice::GetIcon(short &iconSuiteResourceId)
  1063. {
  1064.     iconSuiteResourceId = GetDeviceResID ();
  1065.     
  1066.     return 0;
  1067. }
  1068.  
  1069.  
  1070. void ISpUSBDevice::DoReverse(short dialog_item, Boolean &the_boolean)
  1071. {
  1072.     the_boolean = !the_boolean;
  1073.     SetDialogControl(dialog_item, the_boolean);
  1074.     mDirty = true;
  1075. }
  1076.  
  1077.  
  1078. OSStatus ISpUSBDevice::DialogItemHit(short itemHit)
  1079. {
  1080.     short relHit = itemHit - mBaseDITLCount;
  1081.     
  1082.     switch (relHit)
  1083.     {
  1084.         case kDialogItem_ReverseStick:        DoReverse(relHit, mReverseStick);        break;
  1085.         case kDialogItem_ReverseTrim:        DoReverse(relHit, mReverseTrim);        break;
  1086.         case kDialogItem_ReverseThrottle:     DoReverse(relHit, mReverseThrottle);    break;
  1087.         case kDialogItem_ReverseRudder:        DoReverse(relHit, mReverseRudder);        break;
  1088.         case kDialogItem_ReverseDPad1:         DoReverse(relHit, mReverseDPad[0]);        break;
  1089.         case kDialogItem_ReverseDPad2:         DoReverse(relHit, mReverseDPad[1]);        break;
  1090.         case kDialogItem_ReverseDPad3:         DoReverse(relHit, mReverseDPad[2]);        break;
  1091.         case kDialogItem_ReverseDPad4:         DoReverse(relHit, mReverseDPad[3]);        break;
  1092.     }
  1093.     
  1094.     return noErr;
  1095. }
  1096.  
  1097.  
  1098. OSStatus ISpUSBDevice::GetState(UInt32 buflen, void *buffer, UInt32 &length)
  1099. {
  1100.     WARNING(mVirtualElementsValid,                "ISpUSBDevice: GetState was called but the virtual elemtns were not valid");
  1101.     WARNING((buflen == 0) || (buffer != nil),    "ISpUSBDevice: GetState buffer == nil");
  1102.     
  1103.     USBSetVersion1 *set_vers1_ptr = (USBSetVersion1 *) buffer;
  1104.     length = sizeof(USBSetVersion1);
  1105.  
  1106.     if (length > buflen) { return noErr; }    // required length > space in the buffer, return
  1107.     
  1108.     UInt32 itr;
  1109.     set_vers1_ptr->version = kSetVersion1;
  1110.  
  1111.     for(itr = 1; itr <= kDialogItem_NumPopups; itr++)
  1112.     {
  1113.         set_vers1_ptr->mapping[itr - 1] = mDialogItemToNeedMapping[itr]; // set is zero based array
  1114.     }
  1115.     
  1116.     set_vers1_ptr->flags = 0;
  1117.     
  1118.     if (mReverseStick)            { set_vers1_ptr->flags |= kSetReverseStick; }
  1119.     if (mReverseTrim)            { set_vers1_ptr->flags |= kSetReverseTrim; }
  1120.     if (mReverseThrottle)        { set_vers1_ptr->flags |= kSetReverseThrottle; }
  1121.     if (mReverseRudder)            { set_vers1_ptr->flags |= kSetReverseRudder; }
  1122.     if (mReverseDPad[0])        { set_vers1_ptr->flags |= kSetReverseDPad1; }
  1123.     if (mReverseDPad[1])        { set_vers1_ptr->flags |= kSetReverseDPad2; }
  1124.     if (mReverseDPad[2])        { set_vers1_ptr->flags |= kSetReverseDPad3; }
  1125.     if (mReverseDPad[3])        { set_vers1_ptr->flags |= kSetReverseDPad4; }
  1126.     
  1127.     return noErr;
  1128. }
  1129.  
  1130. OSStatus ISpUSBDevice::SetState(UInt32 length, void *buffer)
  1131. {
  1132.     WARNING(mVirtualElementsValid,                "SetState was called but the virtual elements were not valid");
  1133.     WARNING((length == 0) || (buffer != nil),    "ISpUSBDevice: SetState buffer == nil");
  1134.     WARNING((length > 4),                        "ISpUSBDevice: SetState length < 4");
  1135.  
  1136.     UInt32 itr;
  1137.     
  1138.     // min size check
  1139.     if (length < 4) { return -1;} 
  1140.  
  1141.     UInt32 version = * ((UInt32 *) buffer);
  1142.     
  1143.     switch(version)
  1144.     {
  1145.         case kSetVersion1:
  1146.             if (length == sizeof(USBSetVersion1))
  1147.             {
  1148.                 USBSetVersion1 *set_vers1_ptr = (USBSetVersion1 *) buffer;
  1149.                 
  1150.                 for(itr = 1; itr <= kDialogItem_NumPopups; itr++)
  1151.                 {
  1152.                     mDialogItemToNeedMapping[itr] = set_vers1_ptr->mapping[itr - 1]; // set is zero based array
  1153.                 }
  1154.                 
  1155.                 mReverseStick            = (set_vers1_ptr->flags & kSetReverseStick)            > 0;
  1156.                 mReverseTrim            = (set_vers1_ptr->flags & kSetReverseTrim)            > 0;
  1157.                 mReverseThrottle        = (set_vers1_ptr->flags & kSetReverseThrottle)        > 0;
  1158.                 mReverseRudder            = (set_vers1_ptr->flags & kSetReverseRudder)        > 0;
  1159.                 mReverseDPad[0]            = (set_vers1_ptr->flags & kSetReverseDPad1)            > 0;
  1160.                 mReverseDPad[1]            = (set_vers1_ptr->flags & kSetReverseDPad2)            > 0;
  1161.                 mReverseDPad[2]            = (set_vers1_ptr->flags & kSetReverseDPad3)            > 0;
  1162.                 mReverseDPad[3]            = (set_vers1_ptr->flags & kSetReverseDPad4)            > 0;
  1163.             }
  1164.         break;
  1165.     }
  1166.  
  1167.     SetVirtualElements();
  1168.     
  1169.     if (mVisable)
  1170.     {
  1171.         Draw ();
  1172.             
  1173.  
  1174.         if (features.hasYAxis)
  1175.             SetDialogControl(kDialogItem_ReverseStick,        mReverseStick);
  1176.         
  1177.         if (features.hasTrim)
  1178.             SetDialogControl(kDialogItem_ReverseTrim,        mReverseTrim);
  1179.         
  1180.         if (features.hasThrottle)
  1181.             SetDialogControl(kDialogItem_ReverseThrottle,    mReverseThrottle);
  1182.         
  1183.         if (features.hasRudder)
  1184.             SetDialogControl(kDialogItem_ReverseRudder,        mReverseRudder);
  1185.  
  1186.         UInt32 index;
  1187.         for (index = 0; index < features.numDPads; index++)
  1188.             SetDialogControl(kDialogItem_ReverseDPad1 + index,    mReverseDPad[index]);
  1189.     }
  1190.     
  1191.     mDirty = false;
  1192.     
  1193.     return noErr;
  1194. }
  1195.  
  1196. OSStatus ISpUSBDevice::Tickle(void)
  1197. {
  1198.     return noErr;
  1199. }
  1200.  
  1201. void ISpUSBDevice::SetAsFields(HighLevelData ¤t)
  1202. {
  1203.     AxisToButtons(current.xAxis,        current.xAxis_as_buttons);
  1204.     AxisToButtons(current.yAxis,        current.yAxis_as_buttons);
  1205.     AxisToButtons(current.trim,            current.trim_as_buttons);
  1206.     AxisToButtons(current.throttle,        current.throttle_as_buttons);
  1207.     AxisToButtons(current.rudder,        current.rudder_as_buttons);
  1208.  
  1209.     PedalAxisToButton(current.brake,    current.brake_as_button);
  1210.     PedalAxisToButton(current.gas,        current.gas_as_button);
  1211.  
  1212.     UInt32 itr;
  1213.     for(itr = 0; itr < features.numDPads; itr++)
  1214.     {
  1215.         DPadToButtonsAndAxis (current.dpads[itr], current.dpads_as_buttons[itr], current.dpads_as_axis[itr]);
  1216.     }
  1217. }
  1218.  
  1219. void ISpUSBDevice::PushDataToVirtuals(HighLevelData ¤t)
  1220. {
  1221.     if (mVirtualElementsValid == false)
  1222.         return;
  1223.     
  1224.     OSStatus err;
  1225.     AbsoluteTime time = ISpUptime ();
  1226.     
  1227.     // x and y axis
  1228.     if ((features.hasXAxis) && (features.hasYAxis))
  1229.     {
  1230.         if (((current.xAxis != mOldHLData.xAxis) || (current.yAxis != mOldHLData.yAxis)) && 
  1231.             (virtuals.stickMovement || virtuals.stickDPad) )
  1232.         {
  1233.             ISpMovementData    moveData;
  1234.             
  1235.             moveData.xAxis = current.xAxis;
  1236.             moveData.yAxis = current.yAxis;
  1237.             
  1238.             moveData.direction = AxisToDPad(moveData.xAxis, moveData.yAxis);
  1239.             
  1240.             if (virtuals.stickMovement != nil)
  1241.             {
  1242.                 err = ISpElement_PushComplexData(virtuals.stickMovement, sizeof (moveData), &moveData, &time);
  1243.             }
  1244.             
  1245.             if (virtuals.stickDPad != nil)
  1246.             {
  1247.                 err = ISpElement_PushSimpleData(virtuals.stickDPad, moveData.direction, &time);
  1248.             }
  1249.         }
  1250.     }
  1251.     
  1252.     // *************** X AXIS ***************
  1253.     if (features.hasXAxis)
  1254.     {
  1255.         if ((current.xAxis != mOldHLData.xAxis) && (virtuals.xAxis != nil))
  1256.         {
  1257.             err = ISpElement_PushSimpleData(virtuals.xAxis, current.xAxis, &time);
  1258.         }
  1259.         
  1260.         if ((current.xAxis_as_buttons[0] != mOldHLData.xAxis_as_buttons[0]) && (virtuals.xAxis_as_buttons[0] != nil))
  1261.         {
  1262.             err = ISpElement_PushSimpleData(virtuals.xAxis_as_buttons[0], current.xAxis_as_buttons[0], &time);
  1263.         }
  1264.         
  1265.         if ((current.xAxis_as_buttons[1] != mOldHLData.xAxis_as_buttons[1]) && (virtuals.xAxis_as_buttons[1] != nil))
  1266.         {
  1267.             err = ISpElement_PushSimpleData(virtuals.xAxis_as_buttons[1], current.xAxis_as_buttons[1], &time);
  1268.         }
  1269.     }
  1270.  
  1271.     // *************** Y AXIS ***************
  1272.     if (features.hasYAxis)
  1273.     {
  1274.         if ((current.yAxis != mOldHLData.yAxis) && (virtuals.yAxis != nil))
  1275.         {
  1276.             err = ISpElement_PushSimpleData(virtuals.yAxis, current.yAxis, &time);
  1277.         }
  1278.         
  1279.         if ((current.yAxis_as_buttons[1] != mOldHLData.yAxis_as_buttons[1]) && (virtuals.yAxis_as_buttons[1] != nil))
  1280.         {
  1281.             err = ISpElement_PushSimpleData(virtuals.yAxis_as_buttons[1], current.yAxis_as_buttons[1], &time);
  1282.         }
  1283.         
  1284.         if ((current.yAxis_as_buttons[0] != mOldHLData.yAxis_as_buttons[0]) && (virtuals.yAxis_as_buttons[0] != nil))
  1285.         {
  1286.             err = ISpElement_PushSimpleData(virtuals.yAxis_as_buttons[0], current.yAxis_as_buttons[0], &time);
  1287.         }
  1288.     }
  1289.  
  1290.     // *************** TRIM ***************
  1291.     if (features.hasTrim)
  1292.     {
  1293.         if ((current.trim != mOldHLData.trim) && (virtuals.trim != nil))
  1294.         {
  1295.             err = ISpElement_PushSimpleData(virtuals.trim, current.trim, &time);
  1296.         }
  1297.         
  1298.         if ((current.trim_as_buttons[0] != mOldHLData.trim_as_buttons[0]) && (virtuals.trim_as_buttons[0] != nil))
  1299.         {
  1300.             err = ISpElement_PushSimpleData(virtuals.trim_as_buttons[0], current.trim_as_buttons[0], &time);
  1301.         }
  1302.         
  1303.         if ((current.trim_as_buttons[1] != mOldHLData.trim_as_buttons[1]) && (virtuals.trim_as_buttons[1] != nil))
  1304.         {
  1305.             err = ISpElement_PushSimpleData(virtuals.trim_as_buttons[1], current.trim_as_buttons[1], &time);
  1306.         }
  1307.     }
  1308.  
  1309.     // *************** THROTTLE ***************
  1310.     if (features.hasThrottle)
  1311.     {
  1312.         if ((current.throttle != mOldHLData.throttle) && (virtuals.throttle != nil))
  1313.         {
  1314.             err = ISpElement_PushSimpleData(virtuals.throttle, current.throttle, &time);
  1315.         }
  1316.         
  1317.         if ((current.throttle_as_buttons[0] != mOldHLData.throttle_as_buttons[0]) && (virtuals.throttle_as_buttons[0] != nil))
  1318.         {
  1319.             err = ISpElement_PushSimpleData(virtuals.throttle_as_buttons[0], current.throttle_as_buttons[0], &time);
  1320.         }
  1321.         
  1322.         if ((current.throttle_as_buttons[1] != mOldHLData.throttle_as_buttons[1]) && (virtuals.throttle_as_buttons[1] != nil))
  1323.         {
  1324.             err = ISpElement_PushSimpleData(virtuals.throttle_as_buttons[1], current.throttle_as_buttons[1], &time);
  1325.         }
  1326.     }
  1327.  
  1328.     // *************** RUDDER ***************
  1329.     if (features.hasRudder)
  1330.     {
  1331.         if ((current.rudder != mOldHLData.rudder) && (virtuals.rudder != nil))
  1332.         {
  1333.             err = ISpElement_PushSimpleData(virtuals.rudder, current.rudder, &time);
  1334.         }
  1335.         
  1336.         if ((current.rudder_as_buttons[0] != mOldHLData.rudder_as_buttons[0]) && (virtuals.rudder_as_buttons[0] != nil))
  1337.         {
  1338.             err = ISpElement_PushSimpleData(virtuals.rudder_as_buttons[0], current.rudder_as_buttons[0], &time);
  1339.         }
  1340.         
  1341.         if ((current.rudder_as_buttons[1] != mOldHLData.rudder_as_buttons[1]) && (virtuals.rudder_as_buttons[1] != nil))
  1342.         {
  1343.             err = ISpElement_PushSimpleData(virtuals.rudder_as_buttons[1], current.rudder_as_buttons[1], &time);
  1344.         }
  1345.     }
  1346.  
  1347.     // *************** BRAKE ***************
  1348.     if (features.hasBrake)
  1349.     {
  1350.         if ((current.brake != mOldHLData.brake) && (virtuals.brake != nil))
  1351.         {
  1352.             err = ISpElement_PushSimpleData(virtuals.brake, current.brake, &time);
  1353.         }
  1354.         
  1355.         if ((current.brake_as_button != mOldHLData.brake_as_button) && (virtuals.brake_as_button != nil))
  1356.         {
  1357.             err = ISpElement_PushSimpleData(virtuals.brake_as_button, current.brake_as_button, &time);
  1358.         }
  1359.     }
  1360.  
  1361.     // *************** GAS ***************
  1362.     if (features.hasGas)
  1363.     {
  1364.         if ((current.gas != mOldHLData.gas) && (virtuals.gas != nil))
  1365.         {
  1366.             err = ISpElement_PushSimpleData(virtuals.gas, current.gas, &time);
  1367.         }
  1368.         
  1369.         if ((current.gas_as_button != mOldHLData.gas_as_button) && (virtuals.gas_as_button != nil))
  1370.         {
  1371.             err = ISpElement_PushSimpleData(virtuals.gas_as_button, current.gas_as_button, &time);
  1372.         }
  1373.     }
  1374.     
  1375.     // *************** DPADS ***************
  1376.     UInt32 dpad_itr;
  1377.     for(dpad_itr = 0; dpad_itr < features.numDPads; dpad_itr++)
  1378.     {
  1379.         if ((current.dpads[dpad_itr] != mOldHLData.dpads[dpad_itr]) && (virtuals.dpads[dpad_itr] != nil))
  1380.         {
  1381.             err = ISpElement_PushSimpleData(virtuals.dpads[dpad_itr], current.dpads[dpad_itr], &time);
  1382.         }
  1383.         
  1384.         UInt32 dpad_button_itr;
  1385.         for(dpad_button_itr = 0; dpad_button_itr < 4; dpad_button_itr++)
  1386.         {
  1387.             ISpElementReference this_dpad_button_element = virtuals.dpads_as_buttons[dpad_itr][dpad_button_itr];
  1388.             UInt32 cur_dpad_button_data = current.dpads_as_buttons[dpad_itr][dpad_button_itr];
  1389.             UInt32 old_dpad_button_data = mOldHLData.dpads_as_buttons[dpad_itr][dpad_button_itr];
  1390.             
  1391.             if ((cur_dpad_button_data != old_dpad_button_data) && (this_dpad_button_element != nil))
  1392.             {
  1393.                 err = ISpElement_PushSimpleData(this_dpad_button_element, cur_dpad_button_data, &time);
  1394.             }
  1395.         }
  1396.         
  1397.         Boolean    axisDataChanged = false;
  1398.         
  1399.         UInt32 dpad_axis_itr;
  1400.         for(dpad_axis_itr = 0; dpad_axis_itr < 2; dpad_axis_itr++)
  1401.         {
  1402.             ISpElementReference this_dpad_axis_element = virtuals.dpads_as_axis[dpad_itr][dpad_axis_itr];
  1403.             UInt32 cur_dpad_axis_data = current.dpads_as_axis[dpad_itr][dpad_axis_itr];
  1404.             UInt32 old_dpad_axis_data = mOldHLData.dpads_as_axis[dpad_itr][dpad_axis_itr];
  1405.             
  1406.             if (cur_dpad_axis_data != old_dpad_axis_data)
  1407.             {
  1408.                 axisDataChanged = true;
  1409.                 
  1410.                 if (this_dpad_axis_element != nil)
  1411.                     err = ISpElement_PushSimpleData(this_dpad_axis_element, cur_dpad_axis_data, &time);
  1412.             }
  1413.         }
  1414.  
  1415.         if (axisDataChanged && virtuals.dpads_as_movement[dpad_itr])
  1416.         {
  1417.             ISpMovementData    moveData;
  1418.             
  1419.             moveData.xAxis = current.dpads_as_axis[dpad_itr][0];
  1420.             moveData.yAxis = current.dpads_as_axis[dpad_itr][1];
  1421.             
  1422.             moveData.direction = current.dpads[dpad_itr];
  1423.             
  1424.             if (virtuals.dpads_as_movement[dpad_itr] != nil)
  1425.             {
  1426.                 err = ISpElement_PushComplexData(virtuals.dpads_as_movement[dpad_itr], sizeof (moveData), &moveData, &time);
  1427.             }
  1428.         }
  1429.  
  1430.     }
  1431.     
  1432.     // *************** BUTTONS ***************
  1433.     UInt32 button_itr;
  1434.     for(button_itr = 0; button_itr < features.numButtons; button_itr++)
  1435.     {
  1436.         if ((current.buttons[button_itr] != mOldHLData.buttons[button_itr]) && (virtuals.buttons[button_itr] != nil))
  1437.         {
  1438.             err = ISpElement_PushSimpleData(virtuals.buttons[button_itr], current.buttons[button_itr], &time);
  1439.         }
  1440.     }
  1441.  
  1442. }
  1443.  
  1444. OSStatus ISpUSBDevice::InterruptTickle(void)
  1445. {    
  1446.     return noErr;
  1447. }
  1448.  
  1449. OSStatus ISpUSBDevice::Draw(void)
  1450. {
  1451.     UInt32 itr;
  1452.     
  1453.     for(itr = 0; itr < kDialogItem_NumPopups; itr++)
  1454.     {
  1455.         short itemNo = itr + kDialogItem_FirstPopup + mBaseDITLCount;
  1456.  
  1457.         PlotPopupIcon (itemNo, ttNone);
  1458.     }
  1459.     
  1460.     return noErr;
  1461. }
  1462.  
  1463. OSStatus ISpUSBDevice::Click(const EventRecord &event)
  1464. {
  1465.     // Find the point in local coords
  1466.     Point where;
  1467.     where = event.where;
  1468.     GlobalToLocal(&where);
  1469.  
  1470.     UInt32 itr;
  1471.  
  1472.     for(itr = kDialogItem_FirstPopup; itr <= kDialogItem_NumPopups; itr++)
  1473.     {
  1474.         short itemNo = itr + mBaseDITLCount;
  1475.         UInt32 oldNeed = mDialogItemToNeedMapping[itr];
  1476.         UInt32 newNeed;
  1477.         
  1478.         switch (itr)
  1479.         {
  1480.             case kDialogItem_StickLeft:
  1481.             case kDialogItem_StickRight:
  1482.                 // handle as stick (both axis present) 
  1483.                 if (features.hasXAxis && features.hasYAxis)
  1484.                     HandleStickClick (where, itemNo, 
  1485.                         kDialogItem_StickUp, kDialogItem_StickDown, 
  1486.                         kDialogItem_StickLeft, kDialogItem_StickRight, oldNeed, newNeed);
  1487.                 // handle as axis (both axis not present) 
  1488.                 else if (features.hasXAxis)
  1489.                     HandleAxisClick (where, itemNo, kISpElementLabel_Axis_XAxis, 
  1490.                         kDialogItem_StickLeft, kDialogItem_StickRight, oldNeed, newNeed);
  1491.                 break;
  1492.  
  1493.             case kDialogItem_StickUp:
  1494.             case kDialogItem_StickDown:
  1495.                 // handle as stick (both axis present) 
  1496.                 if (features.hasXAxis && features.hasYAxis)
  1497.                     HandleStickClick (where, itemNo, 
  1498.                         kDialogItem_StickUp, kDialogItem_StickDown, 
  1499.                         kDialogItem_StickLeft, kDialogItem_StickRight, oldNeed, newNeed);
  1500.                 // handle as axis (both axis not present) 
  1501.                 else if (features.hasYAxis)
  1502.                     HandleAxisClick (where, itemNo, kISpElementLabel_Axis_YAxis, 
  1503.                         kDialogItem_StickDown, kDialogItem_StickUp, oldNeed, newNeed);
  1504.                 break;
  1505.  
  1506.             case kDialogItem_TrimLower:
  1507.             case kDialogItem_TrimHigher:
  1508.                 if (features.hasTrim)
  1509.                     HandleAxisClick (where, itemNo, kISpElementLabel_Axis_Trim, 
  1510.                         kDialogItem_TrimLower, kDialogItem_TrimHigher, oldNeed, newNeed);
  1511.                 break;
  1512.  
  1513.             case kDialogItem_ThrottleLower:
  1514.             case kDialogItem_ThrottleHigher:
  1515.                 if (features.hasThrottle)
  1516.                     HandleAxisClick (where, itemNo, kISpElementLabel_Axis_Throttle, 
  1517.                         kDialogItem_ThrottleLower, kDialogItem_ThrottleHigher, oldNeed, newNeed);
  1518.                 break;
  1519.  
  1520.             case kDialogItem_RudderLeft:
  1521.             case kDialogItem_RudderRight:
  1522.                 if (features.hasRudder)
  1523.                     HandleAxisClick (where, itemNo, kISpElementLabel_Axis_Rudder, 
  1524.                         kDialogItem_RudderLeft, kDialogItem_RudderRight, oldNeed, newNeed);
  1525.                 break;
  1526.  
  1527.             case kDialogItem_BrakeDepressed:
  1528.                 if (features.hasBrake)
  1529.                     HandlePedalAxisClick (where, itemNo, kISpElementLabel_Axis_Brake, 
  1530.                         oldNeed, newNeed);
  1531.                 break;
  1532.  
  1533.             case kDialogItem_GasDepressed:
  1534.                 if (features.hasGas)
  1535.                     HandlePedalAxisClick (where, itemNo, kISpElementLabel_Axis_Gas, 
  1536.                         oldNeed, newNeed);
  1537.                 break;
  1538.             
  1539.             case kDialogItem_Button1:
  1540.             case kDialogItem_Button2:
  1541.             case kDialogItem_Button3:
  1542.             case kDialogItem_Button4:
  1543.             case kDialogItem_Button5:
  1544.             case kDialogItem_Button6:
  1545.             case kDialogItem_Button7:
  1546.             case kDialogItem_Button8:
  1547.             case kDialogItem_Button9:
  1548.             case kDialogItem_Button10:
  1549.             case kDialogItem_Button11:
  1550.             case kDialogItem_Button12:
  1551.                 if (features.numButtons > itr - kDialogItem_Button1)
  1552.                     HandleButtonClick (where, itemNo, kISpElementLabel_None, oldNeed, newNeed);
  1553.                 break;
  1554.  
  1555.             case kDialogItem_DPad1Up:
  1556.             case kDialogItem_DPad1Left:
  1557.             case kDialogItem_DPad1Down:
  1558.             case kDialogItem_DPad1Right:
  1559.                 if (features.numDPads >= 1)
  1560.                     HandleDPadClick (where, itemNo,    kDialogItem_DPad1Up, kDialogItem_DPad1Down, 
  1561.                         kDialogItem_DPad1Left, kDialogItem_DPad1Right, oldNeed, newNeed);
  1562.                 break;
  1563.  
  1564.             case kDialogItem_DPad2Up:
  1565.             case kDialogItem_DPad2Left:
  1566.             case kDialogItem_DPad2Down:
  1567.             case kDialogItem_DPad2Right:
  1568.                 if (features.numDPads >= 2)
  1569.                     HandleDPadClick (where, itemNo,    kDialogItem_DPad2Up, kDialogItem_DPad2Down, 
  1570.                         kDialogItem_DPad2Left, kDialogItem_DPad2Right, oldNeed, newNeed);
  1571.                 break;
  1572.  
  1573.             case kDialogItem_DPad3Up:
  1574.             case kDialogItem_DPad3Left:
  1575.             case kDialogItem_DPad3Down:
  1576.             case kDialogItem_DPad3Right:
  1577.                 if (features.numDPads >= 3)
  1578.                     HandleDPadClick (where, itemNo, kDialogItem_DPad3Up, kDialogItem_DPad3Down, 
  1579.                         kDialogItem_DPad3Left, kDialogItem_DPad3Right, oldNeed, newNeed);
  1580.                 break;
  1581.  
  1582.             case kDialogItem_DPad4Up:
  1583.             case kDialogItem_DPad4Left:
  1584.             case kDialogItem_DPad4Down:
  1585.             case kDialogItem_DPad4Right:
  1586.                 if (features.numDPads >= 4)
  1587.                     HandleDPadClick (where, itemNo, kDialogItem_DPad4Up, kDialogItem_DPad4Down, 
  1588.                         kDialogItem_DPad4Left, kDialogItem_DPad4Right, oldNeed, newNeed);
  1589.                 break;
  1590.  
  1591.             default:
  1592.                 break;
  1593.         }        
  1594.     }
  1595.     
  1596.     return noErr;
  1597. }
  1598.  
  1599. OSStatus ISpUSBDevice::ADBReInit(Boolean inPostProcess)
  1600. {
  1601. #pragma unused (inPostProcess)
  1602.     
  1603.     return noErr;
  1604. }
  1605.  
  1606. /*
  1607.  *
  1608.  * SetVirtualElements
  1609.  *
  1610.  * This function takes the virtual index stuff and sets our virtual elements;
  1611.  *
  1612.  */
  1613.  
  1614. void ISpUSBDevice::SetVirtualElements(void)
  1615. {
  1616.     WARNING(mNeeds != nil,                        "ISpUSBDevice::SetVirtualElements but mNeeds was nil");
  1617.     WARNING(mReferences != nil,                    "ISpUSBDevice::SetVirtualElements but mReferences was nil");
  1618.     WARNING(mDialogItemToNeedMapping != nil,    "ISpUSBDevice::SetVirtualElements but mDialogItemToNeedMapping was nil");
  1619.  
  1620. #if DEBUG
  1621.     {
  1622.         UInt32 debug_mapping_itr;
  1623.         
  1624.         for(debug_mapping_itr = 0; debug_mapping_itr < kDialogItem_NumPopups+1; debug_mapping_itr++)
  1625.         {
  1626.             UInt32 debug_mapping = mDialogItemToNeedMapping[debug_mapping_itr];
  1627.             WARNING(((debug_mapping == kUnsetIndex) || (debug_mapping < mNumNeeds)),    "ISpUSBDevice::SetVirtualElements out of range");
  1628.         }
  1629.     }    
  1630. #endif
  1631.  
  1632.     ClearVirtuals ();
  1633.     
  1634.     UInt32    need;
  1635.     
  1636.     // stick up: up button, y axis and movement
  1637.     need = mDialogItemToNeedMapping[kDialogItem_StickUp];
  1638.     if (need != kUnsetIndex)
  1639.         {
  1640.         switch (mNeeds[need].theKind)
  1641.             {
  1642.             case kISpElementKind_Movement:    virtuals.stickMovement = mReferences[need]; break;
  1643.             case kISpElementKind_DPad:        virtuals.stickDPad = mReferences[need]; break;
  1644.             case kISpElementKind_Axis:        virtuals.yAxis = mReferences[need]; break;
  1645.             case kISpElementKind_Button:    virtuals.yAxis_as_buttons[1] = mReferences[need];    break;
  1646.             }
  1647.         }
  1648.         
  1649.     // stick down: down button
  1650.     need = mDialogItemToNeedMapping[kDialogItem_StickDown];
  1651.     if (need != kUnsetIndex)
  1652.         {
  1653.         switch (mNeeds[need].theKind)
  1654.             {
  1655.             case kISpElementKind_Button:    virtuals.yAxis_as_buttons[0] = mReferences[need];    break;
  1656.             }
  1657.         }
  1658.         
  1659.     // stick left: left button and x axis
  1660.     need = mDialogItemToNeedMapping[kDialogItem_StickLeft];
  1661.     if (need != kUnsetIndex)
  1662.         {
  1663.         switch (mNeeds[need].theKind)
  1664.             {
  1665.             case kISpElementKind_Axis:        virtuals.xAxis = mReferences[need]; break;
  1666.             case kISpElementKind_Button:    virtuals.xAxis_as_buttons[0] = mReferences[need];    break;
  1667.             }
  1668.         }
  1669.         
  1670.     // stick right: right button
  1671.     need = mDialogItemToNeedMapping[kDialogItem_StickRight];
  1672.     if (need != kUnsetIndex)
  1673.         {
  1674.         switch (mNeeds[need].theKind)
  1675.             {
  1676.             case kISpElementKind_Button:        virtuals.xAxis_as_buttons[1] = mReferences[need];    break;
  1677.             }
  1678.         }
  1679.         
  1680.     // trim lower: min button and trim axis
  1681.     need = mDialogItemToNeedMapping[kDialogItem_TrimLower];
  1682.     if (need != kUnsetIndex)
  1683.         {
  1684.         switch (mNeeds[need].theKind)
  1685.             {
  1686.             case kISpElementKind_Axis:            virtuals.trim = mReferences[need]; break;
  1687.             case kISpElementKind_Button:        virtuals.trim_as_buttons[0] = mReferences[need];    break;
  1688.             }
  1689.         }
  1690.         
  1691.     // trim higher: max button
  1692.     need = mDialogItemToNeedMapping[kDialogItem_TrimHigher];
  1693.     if (need != kUnsetIndex)
  1694.         {
  1695.         switch (mNeeds[need].theKind)
  1696.             {
  1697.             case kISpElementKind_Button:        virtuals.trim_as_buttons[1] = mReferences[need];    break;
  1698.             }
  1699.         }
  1700.         
  1701.     // throttle lower: min button and throttle axis
  1702.     need = mDialogItemToNeedMapping[kDialogItem_ThrottleLower];
  1703.     if (need != kUnsetIndex)
  1704.         {
  1705.         switch (mNeeds[need].theKind)
  1706.             {
  1707.             case kISpElementKind_Axis:            virtuals.throttle = mReferences[need]; break;
  1708.             case kISpElementKind_Button:        virtuals.throttle_as_buttons[0] = mReferences[need];    break;
  1709.             }
  1710.         }
  1711.         
  1712.     // throttle higher: max button
  1713.     need = mDialogItemToNeedMapping[kDialogItem_ThrottleHigher];
  1714.     if (need != kUnsetIndex)
  1715.         {
  1716.         switch (mNeeds[need].theKind)
  1717.             {
  1718.             case kISpElementKind_Button:        virtuals.throttle_as_buttons[1] = mReferences[need];    break;
  1719.             }
  1720.         }
  1721.         
  1722.     // rudder lower: min button and rudder axis
  1723.     need = mDialogItemToNeedMapping[kDialogItem_RudderLeft];
  1724.     if (need != kUnsetIndex)
  1725.         {
  1726.         switch (mNeeds[need].theKind)
  1727.             {
  1728.             case kISpElementKind_Axis:            virtuals.rudder = mReferences[need]; break;
  1729.             case kISpElementKind_Button:        virtuals.rudder_as_buttons[0] = mReferences[need];    break;
  1730.             }
  1731.         }
  1732.         
  1733.     // rudder higher: max button
  1734.     need = mDialogItemToNeedMapping[kDialogItem_RudderRight];
  1735.     if (need != kUnsetIndex)
  1736.         {
  1737.         switch (mNeeds[need].theKind)
  1738.             {
  1739.             case kISpElementKind_Button:        virtuals.rudder_as_buttons[1] = mReferences[need];    break;
  1740.             }
  1741.         }
  1742.         
  1743.     // brake pedal
  1744.     need = mDialogItemToNeedMapping[kDialogItem_BrakeDepressed];
  1745.     if (need != kUnsetIndex)
  1746.         {
  1747.         switch (mNeeds[need].theKind)
  1748.             {
  1749.             case kISpElementKind_Axis:            virtuals.brake = mReferences[need]; break;
  1750.             case kISpElementKind_Button:        virtuals.brake_as_button = mReferences[need];    break;
  1751.             }
  1752.         }
  1753.         
  1754.     // gas pedal
  1755.     need = mDialogItemToNeedMapping[kDialogItem_GasDepressed];
  1756.     if (need != kUnsetIndex)
  1757.         {
  1758.         switch (mNeeds[need].theKind)
  1759.             {
  1760.             case kISpElementKind_Axis:            virtuals.gas = mReferences[need]; break;
  1761.             case kISpElementKind_Button:        virtuals.gas_as_button = mReferences[need];    break;
  1762.             }
  1763.         }
  1764.         
  1765.     // dpads
  1766.     for (UInt32 dpad_itr = 0; dpad_itr < features.numDPads; dpad_itr++)
  1767.     {
  1768.         // dpad up: up button, y axis, movement, dpad
  1769.         need = mDialogItemToNeedMapping[kDialogItem_DPad1Up + (dpad_itr * 4)];
  1770.         if (need != kUnsetIndex)
  1771.             {
  1772.             switch (mNeeds[need].theKind)
  1773.                 {
  1774.                 case kISpElementKind_DPad:            virtuals.dpads[dpad_itr] = mReferences[need]; break;
  1775.                 case kISpElementKind_Movement:        virtuals.dpads_as_movement[dpad_itr] = mReferences[need]; break;
  1776.                 case kISpElementKind_Axis:            virtuals.dpads_as_axis[dpad_itr][1] = mReferences[need]; break;
  1777.                 case kISpElementKind_Button:        virtuals.dpads_as_buttons[dpad_itr][0] = mReferences[need];    break;
  1778.                 }
  1779.             }
  1780.             
  1781.         // dpad down: down button
  1782.         need = mDialogItemToNeedMapping[kDialogItem_DPad1Down + (dpad_itr * 4)];
  1783.         if (need != kUnsetIndex)
  1784.             {
  1785.             switch (mNeeds[need].theKind)
  1786.                 {
  1787.                 case kISpElementKind_Button:        virtuals.dpads_as_buttons[dpad_itr][2] = mReferences[need];    break;
  1788.                 }
  1789.             }
  1790.             
  1791.         // dpad left: left button and x axis
  1792.         need = mDialogItemToNeedMapping[kDialogItem_DPad1Left + (dpad_itr * 4)];
  1793.         if (need != kUnsetIndex)
  1794.             {
  1795.             switch (mNeeds[need].theKind)
  1796.                 {
  1797.                 case kISpElementKind_Axis:            virtuals.dpads_as_axis[dpad_itr][0] = mReferences[need]; break;
  1798.                 case kISpElementKind_Button:        virtuals.dpads_as_buttons[dpad_itr][1] = mReferences[need];    break;
  1799.                 }
  1800.             }
  1801.             
  1802.         // dpad right: right button
  1803.         need = mDialogItemToNeedMapping[kDialogItem_DPad1Right + (dpad_itr * 4)];
  1804.         if (need != kUnsetIndex)
  1805.             {
  1806.             switch (mNeeds[need].theKind)
  1807.                 {
  1808.                 case kISpElementKind_Button:        virtuals.dpads_as_buttons[dpad_itr][3] = mReferences[need];    break;
  1809.                 }
  1810.             }
  1811.             
  1812.     }
  1813.         
  1814.     // buttons
  1815.     for (UInt32 button_itr = 0; button_itr < features.numButtons; button_itr++)
  1816.     {
  1817.         need = mDialogItemToNeedMapping[kDialogItem_Button1 + button_itr];
  1818.         
  1819.         if (need != kUnsetIndex)
  1820.             virtuals.buttons[button_itr] = mReferences[need];
  1821.     }
  1822. }
  1823.  
  1824. void ISpUSBDevice::ClearVirtuals (void)
  1825. {
  1826.     virtuals.xAxis = nil;
  1827.     virtuals.yAxis = nil;
  1828.     virtuals.trim = nil;
  1829.     virtuals.throttle = nil;
  1830.     virtuals.rudder = nil;
  1831.     virtuals.brake = nil;
  1832.     virtuals.gas = nil;
  1833.  
  1834.     virtuals.stickMovement = nil;
  1835.     virtuals.stickDPad = nil;
  1836.         
  1837.     virtuals.xAxis_as_buttons[0] = nil;
  1838.     virtuals.yAxis_as_buttons[0] = nil;
  1839.     virtuals.trim_as_buttons[0] = nil;
  1840.     virtuals.throttle_as_buttons[0] = nil;
  1841.     virtuals.rudder_as_buttons[0] = nil;
  1842.     virtuals.brake_as_button = nil;
  1843.     virtuals.gas_as_button = nil;
  1844.  
  1845.     virtuals.xAxis_as_buttons[1] = nil;
  1846.     virtuals.yAxis_as_buttons[1] = nil;
  1847.     virtuals.trim_as_buttons[1] = nil;
  1848.     virtuals.throttle_as_buttons[1] = nil;
  1849.     virtuals.rudder_as_buttons[1] = nil;
  1850.  
  1851.     // dpads
  1852.     UInt32 dpad_itr;
  1853.     for(dpad_itr = 0; dpad_itr < kMaxHighLevelDpads; dpad_itr++)
  1854.     {
  1855.         virtuals.dpads[dpad_itr] = nil;
  1856.         virtuals.dpads_as_movement[dpad_itr] = nil;
  1857.         virtuals.dpads_as_buttons[dpad_itr][0] = nil;
  1858.         virtuals.dpads_as_buttons[dpad_itr][1] = nil;
  1859.         virtuals.dpads_as_buttons[dpad_itr][2] = nil;
  1860.         virtuals.dpads_as_buttons[dpad_itr][3] = nil;
  1861.         virtuals.dpads_as_axis[dpad_itr][0] = nil;
  1862.         virtuals.dpads_as_axis[dpad_itr][1] = nil;
  1863.     }
  1864.     
  1865.     // buttons
  1866.     UInt32 button_itr;    
  1867.     for(button_itr = 0; button_itr < kMaxHighLevelButtons; button_itr++)
  1868.     {
  1869.         virtuals.buttons[button_itr] = nil;
  1870.     }
  1871. }
  1872.  
  1873.  
  1874. OSStatus ISpUSBDevice::Initialize(FSSpec fileSpec)
  1875. {
  1876.     OSStatus                        err = noErr;                        
  1877.     short                            resource_ref = -1;            // ref to our resource file
  1878.     Boolean                            resource_file_open = false;    // true if our resource file is open, (we open if we find a device)
  1879.     USBDeviceRef                    usbDeviceRef;
  1880.     CFragConnectionID                usbModuleConnID;
  1881.     UHIDModuleDispatchTablePtr        hidModuleDispatchTable;
  1882.     CFragSymbolClass                symClass;
  1883.     ISpUSBDevice *                    ispUSBDevice = nil;
  1884.     ListNode *                        listNode;
  1885.     
  1886.     int                                dummy = 1;
  1887.     
  1888.     gUSBDevices = List_New();
  1889.     if (!gUSBDevices) return memFullErr;
  1890.     
  1891.     // open the resource file and check for errors
  1892.     if (!resource_file_open)
  1893.     { 
  1894.         resource_ref         = FSpOpenResFile(&fileSpec, fsRdPerm);
  1895.         err                 = ResError();
  1896.  
  1897.         // assert and error check
  1898.         WARNING(err == noErr, "ISpUSBDevice::Initialize failed to open res file");
  1899.         if (err != noErr)  { return err; }
  1900.         
  1901.         resource_file_open    = true;                                        // used to know to close res file
  1902.     }
  1903.     
  1904.     usbDeviceRef = 0;
  1905.     while (!err)
  1906.     {
  1907.         err = USBGetNextDeviceByClass (&usbDeviceRef, &usbModuleConnID, kUSBHIDClass, kUSBNoInterfaceSubClass, kUSBNoInterfaceProtocol);
  1908.         // if error, then either no more devices, or some real errors
  1909.         if (err) break;
  1910.  
  1911.         err = FindSymbol (usbModuleConnID, "\pTheUHIDModuleDispatchTable", (Ptr *)&hidModuleDispatchTable, &symClass);
  1912.         if (err) continue;    // this is not a compliant hid device, doesn't export right symbol
  1913.  
  1914.         // version checking
  1915.         if (hidModuleDispatchTable->dispatchTableCurrentVersion < kOldestCompatableDispatchTableVersion)
  1916.             continue;
  1917.         if (hidModuleDispatchTable->dispatchTableOldestVersion > kCurrentDispatchTableVersion)
  1918.             continue;
  1919.         
  1920.         // in order to make a minimal change, we will claim the device and then immediately release it
  1921.         // if we are successful, because we are going to claim it again in Patch() which is called from 
  1922.         // finish construction below.
  1923.         // however, if we cannot claim the device, the a different driver is already loaded which
  1924.         // talks to the device, so we don't want to create a connection here
  1925.         UHIDModuleConnectionID    connectionID;
  1926.         err = (*hidModuleDispatchTable->pUHIDClaimDevice)(&connectionID, 0);
  1927.         if (err) continue;    // somebody else has cliamed the device, so don't try to get it
  1928.  
  1929.         // we claimed it, so now release it
  1930.         err = (*hidModuleDispatchTable->pUHIDReleaseDevice)(connectionID);
  1931.         WARNING(err == noErr, "USBDevice::Initialize UHIDReleaseDevice failed");
  1932.  
  1933.         // allocate the list node to keep track of our list
  1934.         listNode = List_NewNode(gUSBDevices, kListDontAdd);
  1935.         WARNING(listNode != nil, "ISpUSBDevice failed to allocate list node");
  1936.         if (!listNode) return memFullErr;
  1937.  
  1938.         // for each class, we'll see its supported, and if it is, we'll create it
  1939.         if (TMTopGun::IsTMTopGun(hidModuleDispatchTable))
  1940.             ispUSBDevice = new TMTopGun(hidModuleDispatchTable, usbDeviceRef, fileSpec);
  1941.         else if (GravisPad::IsGravisPad(hidModuleDispatchTable))
  1942.             ispUSBDevice = new GravisPad(hidModuleDispatchTable, usbDeviceRef, fileSpec);
  1943.             
  1944.         // didn't match on any subclass, so we'll give up
  1945.         else
  1946.         {
  1947.             List_DisposeNode(listNode);
  1948.             continue;
  1949.         }
  1950.         
  1951.         // we need to not do a lot of work in constructer, because subclass not created yet
  1952.         ispUSBDevice->FinishConstruction();
  1953.         
  1954.         // if we're here, then we called some classes constructer
  1955.         WARNING(ispUSBDevice != nil, "ISpUSBDevice failed to allocate");
  1956.         
  1957.         listNode->data = ispUSBDevice;
  1958.         List_AddTail(gUSBDevices, listNode);
  1959.     }
  1960.     
  1961.     if (err == kUSBNotFound)
  1962.         err = noErr;    // don't return an error if just no _more_ usb devices
  1963.     
  1964.     // if needed close the resource file
  1965.     if (resource_file_open) { CloseResFile(resource_ref); }
  1966.  
  1967.     return noErr;
  1968. }
  1969.  
  1970. /* =============================================================================
  1971.  *        Terminate (public, static)
  1972.  *
  1973.  *    Gets rid of all our devices.
  1974.  * ========================================================================== */
  1975. void ISpUSBDevice::Terminate(
  1976.     void)
  1977. {
  1978.     void *    listData;
  1979.     
  1980.     List_BeginIteration(gUSBDevices, kListIterateForward, false);
  1981.     
  1982.     // get rid of all the usb devices we created
  1983.     while ((listData = List_Iterate (gUSBDevices)) != nil)
  1984.     {
  1985.         ISpUSBDevice * device = (ISpUSBDevice *) listData;
  1986.         delete device;
  1987.     }
  1988.  
  1989.     List_EndIteration (gUSBDevices);
  1990.     
  1991.     // we'll initialize list, so it's empty in case things go wacky
  1992.     List_Initialize (gUSBDevices);
  1993. }
  1994.  
  1995.  
  1996. void ISpUSBDevice::ParseData(
  1997.     Ptr                        inBuffer)
  1998. {
  1999.     OSStatus err;
  2000.     
  2001.     if (!mActive) return;
  2002.  
  2003.     AbsoluteTime time = ISpUptime();
  2004.     
  2005.     // Parse the data
  2006.     UInt32 itr;
  2007.     for(itr = 0; itr < mUSBElementCount; itr++)
  2008.     {
  2009.         // skip non-valid items
  2010.         if (!mUSBMapping[itr].valid) continue;
  2011.         
  2012.         UInt32 * curHLDataPtr;
  2013.         curHLDataPtr = nil;
  2014.         
  2015.         SInt32 elementValue;
  2016.         elementValue = ParseElementValue(itr, inBuffer);
  2017.         
  2018.         Boolean    shouldReverse = false;
  2019.         
  2020.         UInt32 data = 0;
  2021.         switch (mUSBMapping[itr].kind)
  2022.         {
  2023.             case kISpElementKind_Axis:
  2024.                     double float_data;
  2025.                     
  2026.                     float_data = (elementValue - mUSBMapping[itr].min);
  2027.                     float_data *= mUSBMapping[itr].multiplier;
  2028.                     
  2029.         #if 0
  2030.                     // rudders backwards?
  2031.                     if (mUSBMapping[itr].highIndex == kISpElementLabel_Axis_Rudder)
  2032.                         float_data = kISpAxisMaximum - float_data;
  2033.         #endif
  2034.                     
  2035.                     // clip it
  2036.                     if (float_data < kISpAxisMinimum)
  2037.                         data = kISpAxisMinimum;
  2038.                     else if (float_data > kISpAxisMaximum)
  2039.                         data = kISpAxisMaximum;
  2040.                     else
  2041.                         data = float_data;
  2042.  
  2043.                     switch(mUSBMapping[itr].highIndex)
  2044.                     {
  2045.                         case kISpElementLabel_Axis_XAxis:        curHLDataPtr = &mCurHLData.xAxis;        break;
  2046.                         
  2047.                         case kISpElementLabel_Axis_YAxis:        curHLDataPtr = &mCurHLData.yAxis;
  2048.                                                                 shouldReverse = mReverseStick;            break;
  2049.                                                                 
  2050.                         case kISpElementLabel_Axis_Trim:        curHLDataPtr = &mCurHLData.trim;
  2051.                                                                 shouldReverse = mReverseTrim;            break;
  2052.                                                                 
  2053.                         case kISpElementLabel_Axis_Throttle:    curHLDataPtr = &mCurHLData.throttle;
  2054.                                                                 shouldReverse = mReverseThrottle;        break;
  2055.                                                                 
  2056.                         case kISpElementLabel_Axis_Rudder:        curHLDataPtr = &mCurHLData.rudder;
  2057.                                                                 shouldReverse = mReverseRudder;            break;
  2058.                                                                 
  2059.                         case kISpElementLabel_Axis_Gas:            curHLDataPtr = &mCurHLData.gas;            break;
  2060.                         case kISpElementLabel_Axis_Brake:        curHLDataPtr = &mCurHLData.brake;        break;
  2061.                     }
  2062.                 break;
  2063.             
  2064.             case kISpElementKind_Button:
  2065.                     data = elementValue;
  2066.                     curHLDataPtr = &mCurHLData.buttons[mUSBMapping[itr].highIndex];
  2067.                 break;
  2068.                 
  2069.             case kISpElementKind_DPad:
  2070.                 if (mUSBMapping[itr].usbElementKey != kUSB_dpad4_element)
  2071.                 {
  2072.                     switch  (elementValue)
  2073.                     {
  2074.                         default:
  2075.                         case 0:    data = kISpPadIdle;            break;
  2076.                         case 1:    data = kISpPadUp;             break;
  2077.                         case 2:    data = kISpPadUpRight;        break;
  2078.                         case 3:    data = kISpPadRight;        break;
  2079.                         case 4:    data = kISpPadDownRight;    break;
  2080.                         case 5:    data = kISpPadDown;            break;
  2081.                         case 6:    data = kISpPadDownLeft;        break;
  2082.                         case 7:    data = kISpPadLeft;            break;
  2083.                         case 8:    data = kISpPadUpLeft;        break;
  2084.                     }
  2085.                 }
  2086.                 else
  2087.                 {
  2088.                     switch (elementValue)
  2089.                     {
  2090.                         default:
  2091.                         case 0:    data = kISpPadIdle;            break;
  2092.                         case 1:    data = kISpPadUp;             break;
  2093.                         case 2:    data = kISpPadRight;        break;
  2094.                         case 3:    data = kISpPadDown;            break;
  2095.                         case 4:    data = kISpPadLeft;            break;
  2096.                     }
  2097.                 }
  2098.                 curHLDataPtr = &mCurHLData.dpads[mUSBMapping[itr].highIndex];
  2099.                 shouldReverse = mReverseDPad[mUSBMapping[itr].highIndex];
  2100.                 break;
  2101.         }
  2102.  
  2103.         if (data != mUSBMapping[itr].lastValue)
  2104.         {
  2105.             mUSBMapping[itr].lastValue = data;
  2106.             err = ISpElement_PushSimpleData(mUSBMapping[itr].element, data, &time);
  2107.             
  2108.             // do we need to pass this to the high level ?
  2109.             if (mUSBMapping[itr].highLevelValid && curHLDataPtr)
  2110.             {
  2111.                 if (shouldReverse)
  2112.                 {
  2113.                     switch (mUSBMapping[itr].kind)
  2114.                     {
  2115.                         case kISpElementKind_Axis:
  2116.                             data = kISpAxisMaximum - data;
  2117.                             break;
  2118.                             
  2119.                         case kISpElementKind_DPad:
  2120.                             data = DPadReverseVertical(data);
  2121.                             break;
  2122.                     }
  2123.                 }
  2124.                 
  2125.                 *curHLDataPtr = data;
  2126.             }
  2127.         }
  2128.     }
  2129.     
  2130.     // set the _as_buttons, and _as_axis fields
  2131.     SetAsFields(mCurHLData);
  2132.     
  2133.     // push data into the virtual elements
  2134.     PushDataToVirtuals(mCurHLData);
  2135.     
  2136.     // set the old state
  2137.     mOldHLData = mCurHLData;
  2138. }
  2139.  
  2140. /*
  2141.  *
  2142.  * IsPressed
  2143.  *
  2144.  * This function returns true if this dialog item 'pressed' (ie on the device)
  2145.  *
  2146.  */
  2147.  
  2148. Boolean ISpUSBDevice::IsPressed (short inDialogItem)
  2149. {
  2150.     UInt32 array_index = inDialogItem - mBaseDITLCount - kDialogItem_FirstPopup;
  2151.     
  2152.     WARNING(array_index >= 0,                        "IsPressed array_index out of range (to small)");
  2153.     WARNING(array_index < kDialogItem_NumPopups,    "IsPressed array_index out of range (to large)");
  2154.  
  2155.     return mPopupPressed[array_index];
  2156. }
  2157.  
  2158. void ISpUSBDevice::UpdateAllButtons(void)
  2159. {
  2160.     HighLevelData theHLData = mOldHLData;
  2161.     
  2162.     if (features.hasXAxis)
  2163.     {
  2164.         UpdateSingleButton(theHLData.xAxis_as_buttons[0],        kDialogItem_StickLeft);
  2165.         UpdateSingleButton(theHLData.xAxis_as_buttons[1],        kDialogItem_StickRight);    
  2166.     }
  2167.     if (features.hasYAxis)
  2168.     {
  2169.         UpdateSingleButton(theHLData.yAxis_as_buttons[0],        kDialogItem_StickDown);
  2170.         UpdateSingleButton(theHLData.yAxis_as_buttons[1],        kDialogItem_StickUp);
  2171.     }
  2172.     if (features.hasTrim)
  2173.     {
  2174.         UpdateSingleButton(theHLData.trim_as_buttons[0],        kDialogItem_TrimLower);
  2175.         UpdateSingleButton(theHLData.trim_as_buttons[1],        kDialogItem_TrimHigher);
  2176.     }
  2177.     if (features.hasThrottle)
  2178.     {
  2179.         UpdateSingleButton(theHLData.throttle_as_buttons[0],    kDialogItem_ThrottleLower);
  2180.         UpdateSingleButton(theHLData.throttle_as_buttons[1],    kDialogItem_ThrottleHigher);
  2181.     }
  2182.     if (features.hasRudder)
  2183.     {
  2184.         UpdateSingleButton(theHLData.rudder_as_buttons[0],        kDialogItem_RudderLeft);
  2185.         UpdateSingleButton(theHLData.rudder_as_buttons[1],        kDialogItem_RudderRight);
  2186.     }
  2187.     if (features.hasBrake)
  2188.     {
  2189.         UpdateSingleButton(theHLData.brake_as_button,            kDialogItem_BrakeDepressed);
  2190.     }
  2191.     if (features.hasGas)
  2192.     {
  2193.         UpdateSingleButton(theHLData.gas_as_button,                kDialogItem_GasDepressed);
  2194.     }
  2195.     
  2196.     for(UInt32 button_itr = 0; button_itr < features.numButtons; button_itr++)
  2197.         UpdateSingleButton(theHLData.buttons[button_itr],        kDialogItem_Button1 + button_itr);
  2198.  
  2199.     for (UInt32 dpad_itr = 0; dpad_itr < features.numDPads; dpad_itr++)
  2200.         {
  2201.         UpdateSingleButton(theHLData.dpads_as_buttons[dpad_itr][0],    kDialogItem_DPad1Up + (dpad_itr * 4));
  2202.         UpdateSingleButton(theHLData.dpads_as_buttons[dpad_itr][2],    kDialogItem_DPad1Down + (dpad_itr * 4));
  2203.         UpdateSingleButton(theHLData.dpads_as_buttons[dpad_itr][1],    kDialogItem_DPad1Left + (dpad_itr * 4));
  2204.         UpdateSingleButton(theHLData.dpads_as_buttons[dpad_itr][3],    kDialogItem_DPad1Right + (dpad_itr * 4));
  2205.         }
  2206. }
  2207.  
  2208. void ISpUSBDevice::UpdateSingleButton(UInt32 curButton, UInt32 index)
  2209. {
  2210.     WARNING(mDialog != nil,        "ISpUSBDevice::UpdateSingleButton mDialog was nil");
  2211.     WARNING(mVisable,            "ISpUSBDevice::UpdateSingleButton mVisable was false");
  2212.  
  2213.     WARNING(index > 0,                        "ISpUSBDevice::UpdateSingleButton index out of range (to small)");
  2214.     WARNING(index <= kDialogItem_NumPopups,    "ISpUSBDevice::UpdateSingleButton index out of range (to large)");
  2215.  
  2216.     UInt32 array_index = index - kDialogItem_FirstPopup;
  2217.     Boolean changed = false;    
  2218.     
  2219.     if ((!mPopupPressed[array_index]) && (curButton))
  2220.     {
  2221.         mPopupPressed[array_index] = true;
  2222.         changed = true;
  2223.     }
  2224.     else if ((mPopupPressed[array_index]) && (!curButton))
  2225.     {
  2226.         mPopupPressed[array_index] = false;
  2227.         changed = true;
  2228.     }
  2229.  
  2230.     if (changed)
  2231.         { PlotPopupIcon(mBaseDITLCount + index, ttNone); }
  2232. }
  2233.  
  2234. ////////////////////////////////////////////////////////
  2235.  
  2236.  
  2237. ISpElementLabel USBElementKeyToLabel(short usbElementKey)
  2238. {
  2239.     ISpElementLabel label;
  2240.  
  2241.     switch (usbElementKey)
  2242.     {
  2243.         case kUSB_trigger_element:        label = kISpElementLabel_Btn_Fire;            break;
  2244.         
  2245.         case kUSB_button1_element:        label = kISpElementLabel_None;                break;
  2246.         case kUSB_button2_element:        label = kISpElementLabel_None;                break;
  2247.         case kUSB_button3_element:        label = kISpElementLabel_None;                break;
  2248.         case kUSB_button4_element:        label = kISpElementLabel_None;                break;
  2249.         case kUSB_button5_element:        label = kISpElementLabel_None;                break;
  2250.         case kUSB_button6_element:        label = kISpElementLabel_None;                break;
  2251.         case kUSB_button7_element:        label = kISpElementLabel_None;                break;
  2252.         case kUSB_button8_element:        label = kISpElementLabel_None;                break;
  2253.  
  2254.         case kUSB_buttonSelect_element:    label = kISpElementLabel_Btn_Select;        break;
  2255.         case kUSB_buttonStart_element:    label = kISpElementLabel_Btn_PauseResume;    break;
  2256.         
  2257.         case kUSB_povhat_element:        label = kISpElementLabel_Pad_POV;            break;
  2258.         case kUSB_povhat4_element:        label = kISpElementLabel_Pad_POV;            break;
  2259.         case kUSB_dpad_element:            label = kISpElementLabel_Pad_Move;            break;
  2260.         case kUSB_dpad4_element:        label = kISpElementLabel_Pad_Move;            break;
  2261.         
  2262.         case kUSB_xaxis_element:        label = kISpElementLabel_Axis_XAxis;        break;
  2263.         case kUSB_yaxis_element:        label = kISpElementLabel_Axis_YAxis;        break;
  2264.         case kUSB_throttle_element:        label = kISpElementLabel_Axis_Throttle;        break;
  2265.         case kUSB_rudder_element:        label = kISpElementLabel_Axis_Rudder;        break;
  2266.         case kUSB_trim_element:            label = kISpElementLabel_Axis_Trim;            break;
  2267.         case kUSB_gas_element:            label = kISpElementLabel_Axis_Gas;            break;
  2268.         case kUSB_brake_element:        label = kISpElementLabel_Axis_Brake;        break;
  2269.         case kUSB_axis_element:            label = kISpElementLabel_None;                break;
  2270.  
  2271.         default:                        label = kISpElementLabel_None;                break;
  2272.     }
  2273.         
  2274.     return label;
  2275. }
  2276.  
  2277. OSStatus ISpUSBDevice::BuildMapping(void)
  2278. {
  2279.     UInt32 count; 
  2280.     UInt32 itr;
  2281.     ISpElementDefinitionStruct    def;
  2282.     ISpButtonConfigurationInfo    buttonInfo;
  2283.     ISpDPadConfigurationInfo    dpadInfo;
  2284.     ISpAxisConfigurationInfo    axisInfo;
  2285.     OSStatus err;
  2286.     ISpDeviceReference device;
  2287.  
  2288.     err = CreateDeviceFromResource(GetDeviceResID(), (UInt32) this, device);
  2289.     WARNING(err == noErr, "Failed to create the device in BuildMapping");
  2290.  
  2291.     mDevice = device;
  2292.  
  2293.     def.device = device;
  2294.     def.group = 0;
  2295.     def.dataSize = 4;
  2296.     def.configInfo = 0;
  2297.     def.configInfoLength = 0;
  2298.     def.reserved1 = 0;
  2299.     def.reserved2 = 0;
  2300.     def.reserved3 = 0;
  2301.     
  2302.     count = GetDeviceElementCount();
  2303.     mUSBElementCount = count;
  2304.     mUSBMapping = (USBMapping *) NewPtrSysClear( sizeof(USBMapping) * count );
  2305.     WARNING(!err && mUSBMapping, "Could not allocate mappings in BuildMapping");
  2306.     
  2307.     mNumOrderedButtons = 0;
  2308.     
  2309.     UInt32     buttonCount = 0;
  2310.     UInt32     dpadCount = 0;
  2311.     UInt32    fireButtonCount = 0;
  2312.     
  2313.     AbsoluteTime time = ISpUptime ();
  2314.     
  2315.     for(itr = 0; itr < count; itr++)
  2316.     {
  2317.         USBMapping *thisMapping = &(mUSBMapping[itr]);
  2318.  
  2319.         thisMapping->lastValue = 0;
  2320.         thisMapping->flags = 0;
  2321.         
  2322.         UInt32    elementkey;
  2323.         thisMapping->usbElementKey = elementkey = GetElementKey(itr);
  2324.         
  2325.         Str63 elementName;
  2326.         GetElementName(itr, elementName);
  2327.  
  2328.         // def.label and def.theString
  2329.         CopyPStr(elementName, def.theString, sizeof (def.theString));
  2330.         def.label = USBElementKeyToLabel(elementkey);
  2331.  
  2332.         switch(elementkey)
  2333.         {
  2334.             case kUSB_button1_element:
  2335.             case kUSB_button2_element:
  2336.             case kUSB_button3_element:
  2337.             case kUSB_button4_element:
  2338.             case kUSB_button5_element:
  2339.             case kUSB_button6_element:
  2340.             case kUSB_button7_element:
  2341.             case kUSB_button8_element:
  2342.             case kUSB_trigger_element:
  2343.             case kUSB_buttonStart_element:
  2344.             case kUSB_buttonSelect_element:
  2345.                 // fill in element config info
  2346.                 buttonInfo.id = elementkey;
  2347.                 if (elementkey == kUSB_trigger_element)
  2348.                     buttonInfo.id = 1;    // you should never have _both_ button1 and trigger
  2349.                 else if (elementkey == kUSB_buttonStart_element || elementkey == kUSB_buttonSelect_element)
  2350.                     buttonInfo.id = 0;
  2351.                 
  2352.                 // fill in element definition
  2353.                 def.kind = kISpElementKind_Button;
  2354.                 def.configInfo = &buttonInfo;
  2355.                 def.configInfoLength = sizeof (buttonInfo);
  2356.                 
  2357.                 // fill in mapping structure
  2358.                 thisMapping->kind = kISpElementKind_Button;
  2359.                 thisMapping->valid = true;
  2360.                 
  2361.                 // we haven't reached the most high level buttons we can handle
  2362.                 // make this one do high level stuff as well
  2363.                 if (buttonCount < kMaxHighLevelButtons)
  2364.                 {                
  2365.                     thisMapping->highLevelValid = true;
  2366.                     thisMapping->highIndex = buttonCount;
  2367.     
  2368.                     if (buttonInfo.id != 0)
  2369.                     {
  2370.                         mNumOrderedButtons++;
  2371.                         mOrderedButtonsIndecies[buttonInfo.id - 1] = buttonCount;
  2372.                     }
  2373.  
  2374.                     buttonCount++;
  2375.                 }
  2376.             break;
  2377.             
  2378.             case kUSB_povhat_element:
  2379.             case kUSB_povhat4_element:
  2380.             case kUSB_dpad_element:
  2381.             case kUSB_dpad4_element:
  2382.                 // fill in element config info
  2383.                 dpadInfo.id = 0;    // ignore ordering
  2384.                 dpadInfo.fourWayPad = (elementkey == kUSB_dpad4_element || elementkey == kUSB_povhat4_element);
  2385.                 
  2386.                 // fill in element definition
  2387.                 def.kind = kISpElementKind_DPad;
  2388.                 def.configInfo = &dpadInfo;
  2389.                 def.configInfoLength = sizeof (dpadInfo);
  2390.  
  2391.                 // fill in mapping structure
  2392.                 thisMapping->kind = kISpElementKind_DPad;
  2393.                 thisMapping->valid = true;
  2394.  
  2395.                 // if we havent reached the most high level dpads we can 
  2396.                 // handle make this one do high level stuff as well
  2397.                 if (dpadCount < kMaxHighLevelDpads)
  2398.                 {
  2399.                     thisMapping->highLevelValid = true;
  2400.                     thisMapping->highIndex = dpadCount;
  2401.                     
  2402.                     dpadCount++;
  2403.                 }
  2404.             break;
  2405.             
  2406.             // first we'll do all symmetric axis
  2407.             case kUSB_xaxis_element:
  2408.             case kUSB_yaxis_element:
  2409.             case kUSB_rudder_element:
  2410.             case kUSB_trim_element:
  2411.                 // fill in element config info
  2412.                 axisInfo.symetricAxis = true;
  2413.                 thisMapping->flags |= kMappingFlag_AxisIsSymmetric;
  2414.                 
  2415.                 // fill in element definition
  2416.                 def.kind = kISpElementKind_Axis;
  2417.                 def.configInfo = &axisInfo;
  2418.                 def.configInfoLength = sizeof (axisInfo);
  2419.  
  2420.                 // fill in mapping structure
  2421.                 thisMapping->kind = kISpElementKind_Axis;
  2422.                 thisMapping->valid = true;
  2423.                 thisMapping->min = GetElementMinValue(itr);
  2424.                 thisMapping->max = GetElementMaxValue(itr);
  2425.                 thisMapping->multiplier = kISpAxisMaximum;
  2426.                 thisMapping->multiplier /= (thisMapping->max - thisMapping->min);
  2427.                 
  2428.                 thisMapping->lastValue = kISpAxisMaximum;
  2429.                 
  2430.                 thisMapping->highLevelValid = true;
  2431.                 thisMapping->highIndex = def.label;
  2432.             break;
  2433.  
  2434.             // now we'll do all non-symmetric axis
  2435.             case kUSB_throttle_element:
  2436.             case kUSB_gas_element:
  2437.             case kUSB_brake_element:
  2438.             case kUSB_axis_element:
  2439.                 // fill in element config info
  2440.                 axisInfo.symetricAxis = false;
  2441.                 
  2442.                 // fill in element definition
  2443.                 def.kind = kISpElementKind_Axis;
  2444.                 def.configInfo = &axisInfo;
  2445.                 def.configInfoLength = sizeof (axisInfo);
  2446.  
  2447.                 // fill in mapping structure
  2448.                 thisMapping->kind = kISpElementKind_Axis;
  2449.                 thisMapping->valid = true;
  2450.                 thisMapping->min = GetElementMinValue(itr);
  2451.                 thisMapping->max = GetElementMaxValue(itr);
  2452.                 thisMapping->multiplier = kISpAxisMaximum;
  2453.                 thisMapping->multiplier /= (thisMapping->max - thisMapping->min);
  2454.  
  2455.                 switch(def.label)
  2456.                 {
  2457.                     case kISpElementLabel_Axis_XAxis:
  2458.                     case kISpElementLabel_Axis_YAxis:
  2459.                     case kISpElementLabel_Axis_Trim:
  2460.                     case kISpElementLabel_Axis_Throttle:
  2461.                     case kISpElementLabel_Axis_Rudder:
  2462.                     case kISpElementLabel_Axis_Brake:
  2463.                     case kISpElementLabel_Axis_Gas:
  2464.                         thisMapping->highLevelValid = true;
  2465.                         thisMapping->highIndex = def.label;
  2466.                     break;
  2467.                 }
  2468.             break;
  2469.         }
  2470.         
  2471.         if (thisMapping->valid)
  2472.         {
  2473.             ISpElementReference new_element;
  2474.             
  2475.             err = ISpElement_New(&def, &new_element);
  2476.             WARNING(!err, "pISpElement_New returned an error");
  2477.             
  2478.             mUSBMapping[itr].element = new_element;
  2479.  
  2480.             if (err != noErr) { thisMapping->valid = thisMapping->highLevelValid = false; }
  2481.         }
  2482.         else
  2483.         {
  2484.             thisMapping->element = nil;
  2485.         }
  2486.     }
  2487.     
  2488.     return noErr;
  2489. }
  2490.  
  2491. void ISpUSBDevice::DisposeMapping(void)
  2492. {
  2493.     UInt32 itr;
  2494.     OSStatus err;
  2495.         
  2496.     for(itr = 0; itr < mUSBElementCount; itr++)
  2497.     {
  2498.         if (mUSBMapping[itr].valid)
  2499.         {
  2500.             mUSBMapping[itr].valid = false;
  2501.             
  2502.             err = ISpElement_Dispose(mUSBMapping[itr].element);
  2503.             WARNING(!err, "pISpElementDispose returned an error");
  2504.         }
  2505.     }
  2506.     
  2507.     DisposePtr((Ptr) mUSBMapping);
  2508.     
  2509.     err = ISpDevice_Dispose(mDevice);
  2510.     WARNING(!err, "pISpDevice_Dispose returned an error");
  2511. }
  2512.  
  2513. void    ISpUSBDevice::GetFeatures (void)
  2514. {
  2515.     // clear everything
  2516.     features.hasXAxis = false;
  2517.     features.hasYAxis = false;
  2518.     features.hasTrim = false;
  2519.     features.hasThrottle = false;
  2520.     features.hasRudder = false;
  2521.     features.hasBrake = false;
  2522.     features.hasGas = false;
  2523.  
  2524.     features.numDPads = 0;
  2525.     features.numButtons = 0;
  2526.     features.triggerButtonIndex = kUnsetIndex;
  2527.     features.startButtonIndex = kUnsetIndex;
  2528.     features.selectButtonIndex = kUnsetIndex;
  2529.  
  2530.     features.xAxisIndex = 0;
  2531.     features.yAxisIndex = 0;
  2532.     features.trimIndex = 0;
  2533.     features.throttleIndex = 0;
  2534.     features.rudderIndex = 0;
  2535.     features.brakeIndex = 0;
  2536.     features.gasIndex = 0;
  2537.  
  2538.     {
  2539.         for(UInt32 clearItr = 0; clearItr < kMaxHighLevelButtons; clearItr++)
  2540.             features.buttonIndex[clearItr] = 0;
  2541.     }
  2542.  
  2543.     {
  2544.         for(UInt32 clearItr = 0; clearItr < kMaxHighLevelDpads; clearItr++)
  2545.         {
  2546.             features.dpadIndex[clearItr] = 0;
  2547.             features.is4WayDPad[clearItr] = false;
  2548.         }
  2549.     }
  2550.  
  2551.     // get features
  2552.     UInt8 buttonCount = 0;
  2553.     UInt8 dpadCount = 0;
  2554.  
  2555.     for(UInt32 itr = 0; itr < mUSBElementCount; itr++)
  2556.     {
  2557.         USBMapping *thisMapping = &(mUSBMapping[itr]);
  2558.         
  2559.         if (!thisMapping->valid || !thisMapping->highLevelValid)
  2560.             continue;
  2561.         
  2562.         switch (thisMapping->kind)
  2563.         {
  2564.             case kISpElementKind_Button:
  2565.                 {
  2566.                 ISpElementInfo    info;
  2567.                 OSStatus err = ISpElement_GetInfo(thisMapping->element, &info);
  2568.                 
  2569.                 if (info.theLabel == kISpElementLabel_Btn_Fire && features.triggerButtonIndex == kUnsetIndex)
  2570.                     features.triggerButtonIndex = buttonCount;
  2571.                 else if (info.theLabel == kISpElementLabel_Btn_PauseResume && features.startButtonIndex == kUnsetIndex)
  2572.                     features.startButtonIndex = buttonCount;
  2573.                 else if (info.theLabel == kISpElementLabel_Btn_Select && features.selectButtonIndex == kUnsetIndex)
  2574.                     features.selectButtonIndex = buttonCount;
  2575.                 
  2576.                 if (buttonCount < kMaxHighLevelButtons)
  2577.                     features.buttonIndex[buttonCount] = itr;
  2578.                 
  2579.                 buttonCount++;
  2580.                 }
  2581.                 break;
  2582.             
  2583.             case kISpElementKind_DPad:
  2584.                 {
  2585.                 Boolean is4WayDPad = false;
  2586.  
  2587.                 ISpDPadConfigurationInfo dpadInfo;
  2588.                 OSStatus err = ISpElement_GetConfigurationInfo (thisMapping->element, sizeof (dpadInfo), &dpadInfo);
  2589.                 if (!err) is4WayDPad = dpadInfo.fourWayPad;
  2590.                 
  2591.                 if (dpadCount < kMaxHighLevelDpads)
  2592.                 {
  2593.                     features.dpadIndex[dpadCount] = itr;
  2594.                     features.is4WayDPad[dpadCount] = is4WayDPad;
  2595.                 }
  2596.                 dpadCount++;
  2597.                 }
  2598.                 break;
  2599.             
  2600.             case kISpElementKind_Axis:
  2601.                 {
  2602.                 ISpElementInfo    info;
  2603.                 OSStatus err = ISpElement_GetInfo(thisMapping->element, &info);
  2604.                 
  2605.                 if (!err) switch (info.theLabel)
  2606.                     {
  2607.                     case kISpElementLabel_Axis_XAxis:
  2608.                         if (!features.xAxisIndex)
  2609.                             features.xAxisIndex = itr;
  2610.                         features.hasXAxis = true;
  2611.                         break;
  2612.                     case kISpElementLabel_Axis_YAxis:
  2613.                         if (!features.yAxisIndex)
  2614.                             features.yAxisIndex = itr;
  2615.                         features.hasYAxis = true;
  2616.                         break;
  2617.                     case kISpElementLabel_Axis_Trim:
  2618.                         if (!features.trimIndex)
  2619.                             features.trimIndex = itr;
  2620.                         features.hasTrim = true;
  2621.                         break;
  2622.                     case kISpElementLabel_Axis_Throttle:
  2623.                         if (!features.throttleIndex)
  2624.                             features.throttleIndex = itr;
  2625.                         features.hasThrottle = true;
  2626.                         break;
  2627.                     case kISpElementLabel_Axis_Rudder:
  2628.                         if (!features.rudderIndex)
  2629.                             features.rudderIndex = itr;
  2630.                         features.hasRudder = true;
  2631.                         break;
  2632.                     case kISpElementLabel_Axis_Brake:
  2633.                         if (!features.brakeIndex)
  2634.                             features.brakeIndex = itr;
  2635.                         features.hasBrake = true;
  2636.                         break;
  2637.                     case kISpElementLabel_Axis_Gas:
  2638.                         if (!features.gasIndex)
  2639.                             features.gasIndex = itr;
  2640.                         features.hasGas = true;
  2641.                         break;
  2642.                     }
  2643.                 }
  2644.                 break;
  2645.         }
  2646.     }
  2647.  
  2648.     if (buttonCount > kMaxHighLevelButtons )
  2649.         buttonCount = kMaxHighLevelButtons;
  2650.     
  2651.     if (dpadCount > kMaxHighLevelDpads )
  2652.         dpadCount = kMaxHighLevelDpads;
  2653.  
  2654.     features.numDPads = dpadCount;
  2655.     features.numButtons = buttonCount;
  2656. }
  2657.  
  2658. OSStatus ISpUSBDevice::GetSize(Point &minimum, Point &best)
  2659. {
  2660.     Point    size;
  2661.     
  2662.     // this is the size of the generic DITL, which we'll probably never use except in development
  2663.     size.h = 394;
  2664.     size.v = 316;
  2665.  
  2666.     best = minimum = size;
  2667.  
  2668.     return noErr;
  2669. }
  2670.  
  2671. UInt16 ISpUSBDevice::GetDeviceResID (void)
  2672. {
  2673.     return kResID_Generic;
  2674. }
  2675.  
  2676. UInt32 ISpUSBDevice::GetDeviceElementCount (void) 
  2677. {
  2678.     return 0;
  2679. };
  2680.  
  2681. UInt32 ISpUSBDevice::GetElementKey(UInt32 inElementIndex)
  2682. {
  2683. #pragma unused(inElementIndex)
  2684.  
  2685.     return 0;
  2686. };
  2687.  
  2688. void ISpUSBDevice::GetElementName (UInt32 inElementIndex, Str31 outElementName)
  2689. {
  2690. #pragma unused(inElementIndex)
  2691. #pragma unused(outElementName)
  2692. };
  2693.  
  2694. SInt32 ISpUSBDevice::GetElementMinValue(UInt32 inElementIndex)
  2695. {
  2696. #pragma unused(inElementIndex)
  2697.  
  2698.     return 0;
  2699. };
  2700.  
  2701. SInt32 ISpUSBDevice::GetElementMaxValue(UInt32 inElementIndex)
  2702. {
  2703. #pragma unused(inElementIndex)
  2704.  
  2705.     return 0;
  2706. };
  2707.  
  2708. SInt32 ISpUSBDevice::ParseElementValue(UInt32 inElementIndex, Ptr inBuffer)
  2709. {
  2710. #pragma unused(inElementIndex)
  2711. #pragma unused(inBuffer)
  2712.  
  2713.     return 0;
  2714. };
  2715.  
  2716.  
  2717. // ************************************************************ //
  2718. // *                      TMTopGun                                //
  2719. // ************************************************************ //
  2720.  
  2721. Boolean TMTopGun::IsTMTopGun(UHIDModuleDispatchTablePtr hidmoduleDispatchTable)
  2722. {
  2723.      OSStatus err;
  2724.      UInt16    venderID, productID;
  2725.      
  2726.     err = (*hidmoduleDispatchTable->pUHIDGetDeviceInfo)(kUHIDGetVenderID, &venderID);
  2727.     if (err) return false;
  2728.     
  2729.     err = (*hidmoduleDispatchTable->pUHIDGetDeviceInfo)(kUHIDGetProductID, &productID);
  2730.     if (err) return false;
  2731.     
  2732.     // fail if not our device
  2733.     if (venderID != 0x044f || (productID != 0xa0a0 && productID != 0xa0a1)) return false;
  2734.     
  2735.     return true;
  2736. }
  2737.  
  2738. TMTopGun::TMTopGun (
  2739.     const UHIDModuleDispatchTablePtr hidmoduleDispatchTable,
  2740.     const USBDeviceRef usbDeviceRef,
  2741.     const FSSpec &inFileSpec) : ISpUSBDevice (hidmoduleDispatchTable, usbDeviceRef, inFileSpec)
  2742. {
  2743.     // everything for now is done in our parent's constructer
  2744. }
  2745.  
  2746. TMTopGun::~TMTopGun()
  2747. {
  2748.     // everything for now is done in our parent's destructer
  2749. }
  2750.  
  2751. OSStatus TMTopGun::GetSize(Point &minimum, Point &best)
  2752. {
  2753.     Point    size;
  2754.     
  2755.     size.h = 266;
  2756.     size.v = 200;
  2757.  
  2758.     best = minimum = size;
  2759.  
  2760.     return noErr;
  2761. }
  2762.  
  2763. UInt16 TMTopGun::GetDeviceResID (void)
  2764. {
  2765.     return kResID_TMTopGun;
  2766. }
  2767.  
  2768. UInt32 TMTopGun::GetDeviceElementCount(void)
  2769. {
  2770.     return kTMTopGun_NumElements;
  2771. }
  2772.  
  2773. UInt32 TMTopGun::GetElementKey(UInt32 inElementIndex)
  2774. {
  2775.     switch (inElementIndex)
  2776.     {
  2777.         case kTMTopGun_Hat:                return kUSB_povhat_element;
  2778.         
  2779.         case kTMTopGun_Trigger:            return kUSB_trigger_element;
  2780.         case kTMTopGun_ThumbHigh:        return kUSB_button2_element;
  2781.         case kTMTopGun_ThumbLow:        return kUSB_button3_element;
  2782.         case kTMTopGun_Pinky:            return kUSB_button4_element;
  2783.         
  2784.         case kTMTopGun_XAxis:            return kUSB_xaxis_element;
  2785.         case kTMTopGun_YAxis:            return kUSB_yaxis_element;
  2786.     }
  2787.     
  2788.     return 0;
  2789. }
  2790.  
  2791. void TMTopGun::GetElementName (UInt32 inElementIndex, Str31 outElementName)
  2792. {
  2793.     UInt32 stringIndex;
  2794.  
  2795.     switch (inElementIndex)
  2796.     {
  2797.         case kTMTopGun_Hat:                stringIndex = kStrList_DefaultNames_POVHat;        break;
  2798.         
  2799.         case kTMTopGun_Trigger:            stringIndex = kStrList_DefaultNames_Trigger;    break;
  2800.         case kTMTopGun_ThumbHigh:        stringIndex = kStrList_DefaultNames_Button2;    break;
  2801.         case kTMTopGun_ThumbLow:        stringIndex = kStrList_DefaultNames_Button3;    break;
  2802.         case kTMTopGun_Pinky:            stringIndex = kStrList_DefaultNames_Button4;    break;
  2803.         
  2804.         case kTMTopGun_XAxis:            stringIndex = kStrList_DefaultNames_XAxis;        break;
  2805.         case kTMTopGun_YAxis:            stringIndex = kStrList_DefaultNames_YAxis;        break;
  2806.  
  2807.         default:                        stringIndex = kStrList_DefaultNames_Error;        break;
  2808.     }
  2809.  
  2810.     OSStatus err;
  2811.     Resource_GetIndString(kStrListResource_DefaultNames, stringIndex, sizeof(Str31), outElementName, &err);
  2812.     if (err != noErr) { outElementName[0] = 0; }
  2813. }
  2814.  
  2815. SInt32 TMTopGun::GetElementMinValue(UInt32 inElementIndex)
  2816. {
  2817.     switch (inElementIndex)
  2818.     {
  2819.         case kTMTopGun_Hat:                return 0;
  2820.         
  2821.         case kTMTopGun_Trigger:            return 0;
  2822.         case kTMTopGun_ThumbHigh:        return 0;
  2823.         case kTMTopGun_ThumbLow:        return 0;
  2824.         case kTMTopGun_Pinky:            return 0;
  2825.         
  2826.         case kTMTopGun_XAxis:            return -128;
  2827.         case kTMTopGun_YAxis:            return -127;    // note we flip this so -127 to 128
  2828.     }
  2829.     
  2830.     return 0;
  2831. }
  2832.  
  2833. SInt32 TMTopGun::GetElementMaxValue(UInt32 inElementIndex)
  2834. {
  2835.     switch (inElementIndex)
  2836.     {
  2837.         case kTMTopGun_Hat:                return 1;
  2838.         
  2839.         case kTMTopGun_Trigger:            return 1;
  2840.         case kTMTopGun_ThumbHigh:        return 1;
  2841.         case kTMTopGun_ThumbLow:        return 1;
  2842.         case kTMTopGun_Pinky:            return 1;
  2843.         
  2844.         case kTMTopGun_XAxis:            return 127;
  2845.         case kTMTopGun_YAxis:            return 128;    // note we flip this so -127 to 128
  2846.     }
  2847.     
  2848.     return 0;
  2849. }
  2850.  
  2851. SInt32 TMTopGun::ParseElementValue(UInt32 inElementIndex, Ptr inBuffer)
  2852. {
  2853.     UInt8 * buffer = (UInt8 *) inBuffer;
  2854.     
  2855.     //                 0           1       2        3    
  2856.     // packet is: xxxxxxxx yyyyyyyy bbbbhhhh cccccccc
  2857.     // where b = button, x = x axis, y = y axis, h = hat
  2858.     // button order same as constants
  2859.     
  2860.     switch (inElementIndex)
  2861.     {
  2862.         case kTMTopGun_XAxis:            return ((SInt8) buffer[0]);
  2863.  
  2864.         case kTMTopGun_YAxis:            return (-(SInt32)((SInt8) buffer[1]));    // reverse (flip) this
  2865.  
  2866.         case kTMTopGun_Hat:                return (buffer[2] & 0x0F);    // low 4 bits
  2867.         
  2868.         case kTMTopGun_Trigger:            return !!(buffer[2] & 0x10);
  2869.         case kTMTopGun_ThumbHigh:        return !!(buffer[2] & 0x20);
  2870.         case kTMTopGun_ThumbLow:        return !!(buffer[2] & 0x40);
  2871.         case kTMTopGun_Pinky:            return !!(buffer[2] & 0x80);
  2872.     }
  2873.     
  2874.     return 0;
  2875. }
  2876.  
  2877. // ************************************************************ //
  2878. // *                      GravisPad                                //
  2879. // ************************************************************ //
  2880.  
  2881. Boolean GravisPad::IsGravisPad(UHIDModuleDispatchTablePtr hidmoduleDispatchTable)
  2882. {
  2883.      OSStatus err;
  2884.      UInt16    venderID, productID;
  2885.      
  2886.     err = (*hidmoduleDispatchTable->pUHIDGetDeviceInfo)(kUHIDGetVenderID, &venderID);
  2887.     if (err) return false;
  2888.     
  2889.     err = (*hidmoduleDispatchTable->pUHIDGetDeviceInfo)(kUHIDGetProductID, &productID);
  2890.     if (err) return false;
  2891.     
  2892.     // fail if not our device
  2893.     if (venderID != 0x0428 || productID != 0x55aa) return false;
  2894.     
  2895.     return true;
  2896. }
  2897.  
  2898. GravisPad::GravisPad (
  2899.     const UHIDModuleDispatchTablePtr hidmoduleDispatchTable,
  2900.     const USBDeviceRef usbDeviceRef,
  2901.     const FSSpec &inFileSpec) : ISpUSBDevice (hidmoduleDispatchTable, usbDeviceRef, inFileSpec)
  2902. {
  2903.     // everything for now is done in our parent's constructer
  2904. }
  2905.  
  2906. GravisPad::~GravisPad()
  2907. {
  2908.     // everything for now is done in our parent's destructer
  2909. }
  2910.  
  2911. OSStatus GravisPad::GetSize(Point &minimum, Point &best)
  2912. {
  2913.     Point    size;
  2914.     
  2915.     size.h = 346;
  2916.     size.v = 154;
  2917.  
  2918.     best = minimum = size;
  2919.  
  2920.     return noErr;
  2921. }
  2922.  
  2923. UInt16 GravisPad::GetDeviceResID (void)
  2924. {
  2925.     return kResID_GravisGamepad;
  2926. }
  2927.  
  2928. UInt32 GravisPad::GetDeviceElementCount(void)
  2929. {
  2930.     return kGravisPad_NumElements;
  2931. }
  2932.  
  2933. UInt32 GravisPad::GetElementKey(UInt32 inElementIndex)
  2934. {
  2935.     switch (inElementIndex)
  2936.     {
  2937.         case kGravisPad_DPad:            return kUSB_dpad_element;
  2938.         
  2939.         case kGravisPad_Yellow:            return kUSB_button1_element;
  2940.         case kGravisPad_Red:            return kUSB_button3_element;
  2941.         case kGravisPad_Green:            return kUSB_button2_element;
  2942.         case kGravisPad_Blue:            return kUSB_button4_element;
  2943.         
  2944.         case kGravisPad_LeftTop:        return kUSB_button5_element;
  2945.         case kGravisPad_LeftBottom:        return kUSB_button7_element;
  2946.         case kGravisPad_RightTop:        return kUSB_button6_element;
  2947.         case kGravisPad_RightBottom:    return kUSB_button8_element;
  2948.  
  2949.         case kGravisPad_Select:            return kUSB_buttonSelect_element;
  2950.         case kGravisPad_Start:            return kUSB_buttonStart_element;
  2951.     }
  2952.     
  2953.     return 0;
  2954. }
  2955.  
  2956. void GravisPad::GetElementName (UInt32 inElementIndex, Str31 outElementName)
  2957. {
  2958.     UInt32 stringIndex;
  2959.  
  2960.     switch (inElementIndex)
  2961.     {
  2962.         case kGravisPad_DPad:            stringIndex = kStrList_DefaultNames_DPad;            break;
  2963.         
  2964.         case kGravisPad_Yellow:            stringIndex = kStrList_DefaultNames_YellowButton;    break;
  2965.         case kGravisPad_Red:            stringIndex = kStrList_DefaultNames_RedButton;        break;
  2966.         case kGravisPad_Green:            stringIndex = kStrList_DefaultNames_GreenButton;    break;
  2967.         case kGravisPad_Blue:            stringIndex = kStrList_DefaultNames_BlueButton;        break;
  2968.         
  2969.         case kGravisPad_LeftTop:        stringIndex = kStrList_DefaultNames_LeftIndexTop;        break;
  2970.         case kGravisPad_LeftBottom:        stringIndex = kStrList_DefaultNames_LeftIndexBottom;    break;
  2971.         case kGravisPad_RightTop:        stringIndex = kStrList_DefaultNames_RightIndexTop;        break;
  2972.         case kGravisPad_RightBottom:    stringIndex = kStrList_DefaultNames_RightIndexBottom;    break;
  2973.         
  2974.         case kGravisPad_Select:            stringIndex = kStrList_DefaultNames_SelectButton;    break;
  2975.         case kGravisPad_Start:            stringIndex = kStrList_DefaultNames_StartButton;    break;
  2976.  
  2977.         default:                        stringIndex = kStrList_DefaultNames_Error;            break;
  2978.     }
  2979.  
  2980.     OSStatus err;
  2981.     Resource_GetIndString(kStrListResource_DefaultNames, stringIndex, sizeof(Str31), outElementName, &err);
  2982.     if (err != noErr) { outElementName[0] = 0; }
  2983. }
  2984.  
  2985. SInt32 GravisPad::GetElementMinValue(UInt32 inElementIndex)
  2986. {
  2987.     switch (inElementIndex)
  2988.     {
  2989.         case kGravisPad_DPad:            return 0;
  2990.         
  2991.         case kGravisPad_Yellow:            return 0;
  2992.         case kGravisPad_Red:            return 0;
  2993.         case kGravisPad_Green:            return 0;
  2994.         case kGravisPad_Blue:            return 0;
  2995.         
  2996.         case kGravisPad_LeftTop:        return 0;
  2997.         case kGravisPad_LeftBottom:        return 0;
  2998.         case kGravisPad_RightTop:        return 0;
  2999.         case kGravisPad_RightBottom:    return 0;
  3000.         
  3001.         case kGravisPad_Select:            return 0;
  3002.         case kGravisPad_Start:            return 0;
  3003.     }
  3004.     
  3005.     return 0;
  3006. }
  3007.  
  3008. SInt32 GravisPad::GetElementMaxValue(UInt32 inElementIndex)
  3009. {
  3010.     switch (inElementIndex)
  3011.     {
  3012.         case kGravisPad_DPad:            return 8;
  3013.         
  3014.         case kGravisPad_Yellow:            return 1;
  3015.         case kGravisPad_Red:            return 1;
  3016.         case kGravisPad_Green:            return 1;
  3017.         case kGravisPad_Blue:            return 1;
  3018.         
  3019.         case kGravisPad_LeftTop:        return 1;
  3020.         case kGravisPad_LeftBottom:        return 1;
  3021.         case kGravisPad_RightTop:        return 1;
  3022.         case kGravisPad_RightBottom:    return 1;
  3023.         
  3024.         case kGravisPad_Select:            return 1;
  3025.         case kGravisPad_Start:            return 1;
  3026.     }
  3027.     
  3028.     return 0;
  3029. }
  3030.  
  3031. SInt32 GravisPad::ParseElementValue(UInt32 inElementIndex, Ptr inBuffer)
  3032. {
  3033.     UInt8 * buffer = (UInt8 *) inBuffer;
  3034.     UInt32    xaxis, yaxis;
  3035.     
  3036.     //                 0           1       2        3    
  3037.     // packet is: xxxxxxxx yyyyyyyy bbbbbbbb ccccccbb
  3038.     // where b = button, x = x axis, y = y axis
  3039.     // button order same as constants
  3040.     
  3041.     switch (inElementIndex)
  3042.     {
  3043.         case kGravisPad_DPad:
  3044.             // we know it's really a dpad, so we're gonna convert it to usb like dpad values
  3045.             xaxis     = buffer[0];
  3046.             yaxis     = buffer[1];
  3047.  
  3048.             if (yaxis > 0xbf)                         // is down + ...
  3049.             {
  3050.                 if (xaxis < 0x3f) return 6;                // is left
  3051.                 else if (xaxis > 0xbf) return 4;        // is right
  3052.                 else return 5;                            // is middle
  3053.             
  3054.             }
  3055.             else if (yaxis < 0x3f)                     // is up + ...
  3056.             {
  3057.                 if (xaxis < 0x3f) return 8;                // is left
  3058.                 else if (xaxis > 0xbf) return 2;        // is right
  3059.                 else return 1;                            // is middle
  3060.             }
  3061.             else                                     // is middle + ...
  3062.             {
  3063.                 if (xaxis < 0x3f) return 7;                // is left
  3064.                 else if (xaxis > 0xbf) return 3;        // is right
  3065.                 else return 0;                            // is middle
  3066.             }
  3067.                     
  3068.         case kGravisPad_Yellow:            return !!(buffer[2] & 0x02);
  3069.         case kGravisPad_Red:            return !!(buffer[2] & 0x01);
  3070.         case kGravisPad_Green:            return !!(buffer[2] & 0x04);
  3071.         case kGravisPad_Blue:            return !!(buffer[2] & 0x08);
  3072.         
  3073.         case kGravisPad_LeftBottom:        return !!(buffer[2] & 0x10);
  3074.         case kGravisPad_RightBottom:    return !!(buffer[2] & 0x20);
  3075.         case kGravisPad_LeftTop:        return !!(buffer[2] & 0x40);
  3076.         case kGravisPad_RightTop:        return !!(buffer[2] & 0x80);
  3077.  
  3078.         case kGravisPad_Select:            return !!(buffer[3] & 0x01);
  3079.         case kGravisPad_Start:            return !!(buffer[3] & 0x02);
  3080.     }
  3081.     
  3082.     return 0;
  3083. }
  3084.  
  3085.  
  3086.